diff --git a/gui/gnome/autocustom-gnome-macos/conf/.p10k.zsh b/gui/gnome/autocustom-gnome-macos/conf/.p10k.zsh deleted file mode 100644 index 5e9b5b2e..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/.p10k.zsh +++ /dev/null @@ -1,1842 +0,0 @@ -# Generated by Powerlevel10k configuration wizard on 2024-05-23 at 22:00 EDT. -# Based on romkatv/powerlevel10k/config/p10k-rainbow.zsh, checksum 44011. -# Wizard options: nerdfont-complete + powerline, small icons, rainbow, unicode, -# angled separators, flat heads, flat tails, 2 lines, disconnected, full frame, -# dark-ornaments, sparse, many icons, concise, instant_prompt=quiet. -# Type `p10k configure` to generate another config. -# -# Config for Powerlevel10k with powerline prompt style with colorful background. -# Type `p10k configure` to generate your own config based on it. -# -# Tip: Looking for a nice color? Here's a one-liner to print colormap. -# -# for i in {0..255}; do print -Pn "%K{$i} %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$'\n'}; done - -# Temporarily change options. -'builtin' 'local' '-a' 'p10k_config_opts' -[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases') -[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob') -[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand') -'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand' - -() { - emulate -L zsh -o extended_glob - - # Unset all configuration options. This allows you to apply configuration changes without - # restarting zsh. Edit ~/.p10k.zsh and type `source ~/.p10k.zsh`. - unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR' - - # Zsh >= 5.1 is required. - [[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return - - # The list of segments shown on the left. Fill it with the most important segments. - typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( - # =========================[ Line #1 ]========================= - os_icon # os identifier - dir # current directory - vcs # git status - # =========================[ Line #2 ]========================= - newline # \n - # prompt_char # prompt symbol - ) - - # The list of segments shown on the right. Fill it with less important segments. - # Right prompt on the last prompt line (where you are typing your commands) gets - # automatically hidden when the input line reaches it. Right prompt above the - # last prompt line gets hidden if it would overlap with left prompt. - typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=( - # =========================[ Line #1 ]========================= - status # exit code of the last command - command_execution_time # duration of the last command - background_jobs # presence of background jobs - direnv # direnv status (https://direnv.net/) - asdf # asdf version manager (https://github.com/asdf-vm/asdf) - virtualenv # python virtual environment (https://docs.python.org/3/library/venv.html) - anaconda # conda environment (https://conda.io/) - pyenv # python environment (https://github.com/pyenv/pyenv) - goenv # go environment (https://github.com/syndbg/goenv) - nodenv # node.js version from nodenv (https://github.com/nodenv/nodenv) - nvm # node.js version from nvm (https://github.com/nvm-sh/nvm) - nodeenv # node.js environment (https://github.com/ekalinin/nodeenv) - # node_version # node.js version - # go_version # go version (https://golang.org) - # rust_version # rustc version (https://www.rust-lang.org) - # dotnet_version # .NET version (https://dotnet.microsoft.com) - # php_version # php version (https://www.php.net/) - # laravel_version # laravel php framework version (https://laravel.com/) - # java_version # java version (https://www.java.com/) - # package # name@version from package.json (https://docs.npmjs.com/files/package.json) - rbenv # ruby version from rbenv (https://github.com/rbenv/rbenv) - rvm # ruby version from rvm (https://rvm.io) - fvm # flutter version management (https://github.com/leoafarias/fvm) - luaenv # lua version from luaenv (https://github.com/cehoffman/luaenv) - jenv # java version from jenv (https://github.com/jenv/jenv) - plenv # perl version from plenv (https://github.com/tokuhirom/plenv) - perlbrew # perl version from perlbrew (https://github.com/gugod/App-perlbrew) - phpenv # php version from phpenv (https://github.com/phpenv/phpenv) - scalaenv # scala version from scalaenv (https://github.com/scalaenv/scalaenv) - haskell_stack # haskell version from stack (https://haskellstack.org/) - kubecontext # current kubernetes context (https://kubernetes.io/) - terraform # terraform workspace (https://www.terraform.io) - # terraform_version # terraform version (https://www.terraform.io) - aws # aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) - aws_eb_env # aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/) - azure # azure account name (https://docs.microsoft.com/en-us/cli/azure) - gcloud # google cloud cli account and project (https://cloud.google.com/) - google_app_cred # google application credentials (https://cloud.google.com/docs/authentication/production) - toolbox # toolbox name (https://github.com/containers/toolbox) - context # user@hostname - nordvpn # nordvpn connection status, linux only (https://nordvpn.com/) - ranger # ranger shell (https://github.com/ranger/ranger) - yazi # yazi shell (https://github.com/sxyazi/yazi) - nnn # nnn shell (https://github.com/jarun/nnn) - lf # lf shell (https://github.com/gokcehan/lf) - xplr # xplr shell (https://github.com/sayanarijit/xplr) - vim_shell # vim shell indicator (:sh) - midnight_commander # midnight commander shell (https://midnight-commander.org/) - nix_shell # nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html) - chezmoi_shell # chezmoi shell (https://www.chezmoi.io/) - vi_mode # vi mode (you don't need this if you've enabled prompt_char) - # vpn_ip # virtual private network indicator - # load # CPU load - # disk_usage # disk usage - # ram # free RAM - # swap # used swap - todo # todo items (https://github.com/todotxt/todo.txt-cli) - timewarrior # timewarrior tracking status (https://timewarrior.net/) - taskwarrior # taskwarrior task count (https://taskwarrior.org/) - per_directory_history # Oh My Zsh per-directory-history local/global indicator - # cpu_arch # CPU architecture - # time # current time - # =========================[ Line #2 ]========================= - newline - # ip # ip address and bandwidth usage for a specified network interface - # public_ip # public IP address - # proxy # system-wide http/https/ftp proxy - # battery # internal battery - # wifi # wifi speed - # example # example user-defined segment (see prompt_example function below) - ) - - # Defines character set used by powerlevel10k. It's best to let `p10k configure` set it for you. - typeset -g POWERLEVEL9K_MODE=nerdfont-complete - # When set to `moderate`, some icons will have an extra space after them. This is meant to avoid - # icon overlap when using non-monospace fonts. When set to `none`, spaces are not added. - typeset -g POWERLEVEL9K_ICON_PADDING=none - - # When set to true, icons appear before content on both sides of the prompt. When set - # to false, icons go after content. If empty or not set, icons go before content in the left - # prompt and after content in the right prompt. - # - # You can also override it for a specific segment: - # - # POWERLEVEL9K_STATUS_ICON_BEFORE_CONTENT=false - # - # Or for a specific segment in specific state: - # - # POWERLEVEL9K_DIR_NOT_WRITABLE_ICON_BEFORE_CONTENT=false - typeset -g POWERLEVEL9K_ICON_BEFORE_CONTENT= - - # Add an empty line before each prompt. - typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=true - - # Connect left prompt lines with these symbols. You'll probably want to use the same color - # as POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_FOREGROUND below. - typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX='%240F╭─' - typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX='%240F├─' - typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX='%240F╰─' - # Connect right prompt lines with these symbols. - typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX='%240F─╮' - typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX='%240F─┤' - typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX='%240F─╯' - - # Filler between left and right prompt on the first prompt line. You can set it to ' ', '·' or - # '─'. The last two make it easier to see the alignment between left and right prompt and to - # separate prompt from command output. You might want to set POWERLEVEL9K_PROMPT_ADD_NEWLINE=false - # for more compact prompt if using this option. - typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' ' - typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_BACKGROUND= - typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_GAP_BACKGROUND= - if [[ $POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR != ' ' ]]; then - # The color of the filler. You'll probably want to match the color of POWERLEVEL9K_MULTILINE - # ornaments defined above. - typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_FOREGROUND=240 - # Start filler from the edge of the screen if there are no left segments on the first line. - typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_FIRST_SEGMENT_END_SYMBOL='%{%}' - # End filler on the edge of the screen if there are no right segments on the first line. - typeset -g POWERLEVEL9K_EMPTY_LINE_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='%{%}' - fi - - # Separator between same-color segments on the left. - typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR='\uE0B1' - # Separator between same-color segments on the right. - typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR='\uE0B3' - # Separator between different-color segments on the left. - typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR='\uE0B0' - # Separator between different-color segments on the right. - typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR='\uE0B2' - # To remove a separator between two segments, add "_joined" to the second segment name. - # For example: POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(os_icon context_joined) - - # The right end of left prompt. - typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL='' - # The left end of right prompt. - typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='' - # The left end of left prompt. - typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL='' - # The right end of right prompt. - typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL='' - # Left prompt terminator for lines without any segments. - typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL= - - #################################[ os_icon: os identifier ]################################## - # OS identifier color. - typeset -g POWERLEVEL9K_OS_ICON_FOREGROUND=232 - typeset -g POWERLEVEL9K_OS_ICON_BACKGROUND=7 - # Custom icon. - # typeset -g POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION='⭐' - - ################################[ prompt_char: prompt symbol ]################################ - # Transparent background. - typeset -g POWERLEVEL9K_PROMPT_CHAR_BACKGROUND= - # Green prompt symbol if the last command succeeded. - typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=76 - # Red prompt symbol if the last command failed. - typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=196 - # Default prompt symbol. - typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION='❯' - # Prompt symbol in command vi mode. - typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION='❮' - # Prompt symbol in visual vi mode. - typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='V' - # Prompt symbol in overwrite vi mode. - typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIOWR_CONTENT_EXPANSION='▶' - typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=true - # No line terminator if prompt_char is the last segment. - typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL= - # No line introducer if prompt_char is the first segment. - typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL= - # No surrounding whitespace. - typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_{LEFT,RIGHT}_WHITESPACE= - - ##################################[ dir: current directory ]################################## - # Current directory background color. - typeset -g POWERLEVEL9K_DIR_BACKGROUND=4 - # Default current directory foreground color. - typeset -g POWERLEVEL9K_DIR_FOREGROUND=254 - # If directory is too long, shorten some of its segments to the shortest possible unique - # prefix. The shortened directory can be tab-completed to the original. - typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique - # Replace removed segment suffixes with this symbol. - typeset -g POWERLEVEL9K_SHORTEN_DELIMITER= - # Color of the shortened directory segments. - typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=250 - # Color of the anchor directory segments. Anchor segments are never shortened. The first - # segment is always an anchor. - typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=255 - # Display anchor directory segments in bold. - typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=true - # Don't shorten directories that contain any of these files. They are anchors. - local anchor_files=( - .bzr - .citc - .git - .hg - .node-version - .python-version - .go-version - .ruby-version - .lua-version - .java-version - .perl-version - .php-version - .tool-versions - .shorten_folder_marker - .svn - .terraform - CVS - Cargo.toml - composer.json - go.mod - package.json - stack.yaml - ) - typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER="(${(j:|:)anchor_files})" - # If set to "first" ("last"), remove everything before the first (last) subdirectory that contains - # files matching $POWERLEVEL9K_SHORTEN_FOLDER_MARKER. For example, when the current directory is - # /foo/bar/git_repo/nested_git_repo/baz, prompt will display git_repo/nested_git_repo/baz (first) - # or nested_git_repo/baz (last). This assumes that git_repo and nested_git_repo contain markers - # and other directories don't. - # - # Optionally, "first" and "last" can be followed by ":" where is an integer. - # This moves the truncation point to the right (positive offset) or to the left (negative offset) - # relative to the marker. Plain "first" and "last" are equivalent to "first:0" and "last:0" - # respectively. - typeset -g POWERLEVEL9K_DIR_TRUNCATE_BEFORE_MARKER=false - # Don't shorten this many last directory segments. They are anchors. - typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1 - # Shorten directory if it's longer than this even if there is space for it. The value can - # be either absolute (e.g., '80') or a percentage of terminal width (e.g, '50%'). If empty, - # directory will be shortened only when prompt doesn't fit or when other parameters demand it - # (see POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS and POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT below). - # If set to `0`, directory will always be shortened to its minimum length. - typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80 - # When `dir` segment is on the last prompt line, try to shorten it enough to leave at least this - # many columns for typing commands. - typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40 - # When `dir` segment is on the last prompt line, try to shorten it enough to leave at least - # COLUMNS * POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT * 0.01 columns for typing commands. - typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50 - # If set to true, embed a hyperlink into the directory. Useful for quickly - # opening a directory in the file manager simply by clicking the link. - # Can also be handy when the directory is shortened, as it allows you to see - # the full directory that was used in previous commands. - typeset -g POWERLEVEL9K_DIR_HYPERLINK=false - - # Enable special styling for non-writable and non-existent directories. See POWERLEVEL9K_LOCK_ICON - # and POWERLEVEL9K_DIR_CLASSES below. - typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=v3 - - # The default icon shown next to non-writable and non-existent directories when - # POWERLEVEL9K_DIR_SHOW_WRITABLE is set to v3. - # typeset -g POWERLEVEL9K_LOCK_ICON='⭐' - - # POWERLEVEL9K_DIR_CLASSES allows you to specify custom icons and colors for different - # directories. It must be an array with 3 * N elements. Each triplet consists of: - # - # 1. A pattern against which the current directory ($PWD) is matched. Matching is done with - # extended_glob option enabled. - # 2. Directory class for the purpose of styling. - # 3. An empty string. - # - # Triplets are tried in order. The first triplet whose pattern matches $PWD wins. - # - # If POWERLEVEL9K_DIR_SHOW_WRITABLE is set to v3, non-writable and non-existent directories - # acquire class suffix _NOT_WRITABLE and NON_EXISTENT respectively. - # - # For example, given these settings: - # - # typeset -g POWERLEVEL9K_DIR_CLASSES=( - # '~/work(|/*)' WORK '' - # '~(|/*)' HOME '' - # '*' DEFAULT '') - # - # Whenever the current directory is ~/work or a subdirectory of ~/work, it gets styled with one - # of the following classes depending on its writability and existence: WORK, WORK_NOT_WRITABLE or - # WORK_NON_EXISTENT. - # - # Simply assigning classes to directories doesn't have any visible effects. It merely gives you an - # option to define custom colors and icons for different directory classes. - # - # # Styling for WORK. - # typeset -g POWERLEVEL9K_DIR_WORK_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_DIR_WORK_BACKGROUND=4 - # typeset -g POWERLEVEL9K_DIR_WORK_FOREGROUND=254 - # typeset -g POWERLEVEL9K_DIR_WORK_SHORTENED_FOREGROUND=250 - # typeset -g POWERLEVEL9K_DIR_WORK_ANCHOR_FOREGROUND=255 - # - # # Styling for WORK_NOT_WRITABLE. - # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_BACKGROUND=4 - # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_FOREGROUND=254 - # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_SHORTENED_FOREGROUND=250 - # typeset -g POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_ANCHOR_FOREGROUND=255 - # - # # Styling for WORK_NON_EXISTENT. - # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_BACKGROUND=4 - # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_FOREGROUND=254 - # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_SHORTENED_FOREGROUND=250 - # typeset -g POWERLEVEL9K_DIR_WORK_NON_EXISTENT_ANCHOR_FOREGROUND=255 - # - # If a styling parameter isn't explicitly defined for some class, it falls back to the classless - # parameter. For example, if POWERLEVEL9K_DIR_WORK_NOT_WRITABLE_FOREGROUND is not set, it falls - # back to POWERLEVEL9K_DIR_FOREGROUND. - # - # typeset -g POWERLEVEL9K_DIR_CLASSES=() - - # Custom prefix. - # typeset -g POWERLEVEL9K_DIR_PREFIX='in ' - - #####################################[ vcs: git status ]###################################### - # Version control background colors. - typeset -g POWERLEVEL9K_VCS_CLEAN_BACKGROUND=2 - typeset -g POWERLEVEL9K_VCS_MODIFIED_BACKGROUND=3 - typeset -g POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND=2 - typeset -g POWERLEVEL9K_VCS_CONFLICTED_BACKGROUND=3 - typeset -g POWERLEVEL9K_VCS_LOADING_BACKGROUND=8 - - # Branch icon. Set this parameter to '\UE0A0 ' for the popular Powerline branch icon. - typeset -g POWERLEVEL9K_VCS_BRANCH_ICON='\uF126 ' - - # Untracked files icon. It's really a question mark, your font isn't broken. - # Change the value of this parameter to show a different icon. - typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?' - - # Formatter for Git status. - # - # Example output: master wip ⇣42⇡42 *42 merge ~42 +42 !42 ?42. - # - # You can edit the function to customize how Git status looks. - # - # VCS_STATUS_* parameters are set by gitstatus plugin. See reference: - # https://github.com/romkatv/gitstatus/blob/master/gitstatus.plugin.zsh. - function my_git_formatter() { - emulate -L zsh - - if [[ -n $P9K_CONTENT ]]; then - # If P9K_CONTENT is not empty, use it. It's either "loading" or from vcs_info (not from - # gitstatus plugin). VCS_STATUS_* parameters are not available in this case. - typeset -g my_git_format=$P9K_CONTENT - return - fi - - # Styling for different parts of Git status. - local meta='%7F' # white foreground - local clean='%0F' # black foreground - local modified='%0F' # black foreground - local untracked='%0F' # black foreground - local conflicted='%1F' # red foreground - - local res - - if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then - local branch=${(V)VCS_STATUS_LOCAL_BRANCH} - # If local branch name is at most 32 characters long, show it in full. - # Otherwise show the first 12 … the last 12. - # Tip: To always show local branch name in full without truncation, delete the next line. - (( $#branch > 32 )) && branch[13,-13]="…" # <-- this line - res+="${clean}${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}${branch//\%/%%}" - fi - - if [[ -n $VCS_STATUS_TAG - # Show tag only if not on a branch. - # Tip: To always show tag, delete the next line. - && -z $VCS_STATUS_LOCAL_BRANCH # <-- this line - ]]; then - local tag=${(V)VCS_STATUS_TAG} - # If tag name is at most 32 characters long, show it in full. - # Otherwise show the first 12 … the last 12. - # Tip: To always show tag name in full without truncation, delete the next line. - (( $#tag > 32 )) && tag[13,-13]="…" # <-- this line - res+="${meta}#${clean}${tag//\%/%%}" - fi - - # Display the current Git commit if there is no branch and no tag. - # Tip: To always display the current Git commit, delete the next line. - [[ -z $VCS_STATUS_LOCAL_BRANCH && -z $VCS_STATUS_TAG ]] && # <-- this line - res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}" - - # Show tracking branch name if it differs from local branch. - if [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]]; then - res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}" - fi - - # Display "wip" if the latest commit's summary contains "wip" or "WIP". - if [[ $VCS_STATUS_COMMIT_SUMMARY == (|*[^[:alnum:]])(wip|WIP)(|[^[:alnum:]]*) ]]; then - res+=" ${modified}wip" - fi - - if (( VCS_STATUS_COMMITS_AHEAD || VCS_STATUS_COMMITS_BEHIND )); then - # ⇣42 if behind the remote. - (( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}⇣${VCS_STATUS_COMMITS_BEHIND}" - # ⇡42 if ahead of the remote; no leading space if also behind the remote: ⇣42⇡42. - (( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" " - (( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}⇡${VCS_STATUS_COMMITS_AHEAD}" - elif [[ -n $VCS_STATUS_REMOTE_BRANCH ]]; then - # Tip: Uncomment the next line to display '=' if up to date with the remote. - # res+=" ${clean}=" - fi - - # ⇠42 if behind the push remote. - (( VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" ${clean}⇠${VCS_STATUS_PUSH_COMMITS_BEHIND}" - (( VCS_STATUS_PUSH_COMMITS_AHEAD && !VCS_STATUS_PUSH_COMMITS_BEHIND )) && res+=" " - # ⇢42 if ahead of the push remote; no leading space if also behind: ⇠42⇢42. - (( VCS_STATUS_PUSH_COMMITS_AHEAD )) && res+="${clean}⇢${VCS_STATUS_PUSH_COMMITS_AHEAD}" - # *42 if have stashes. - (( VCS_STATUS_STASHES )) && res+=" ${clean}*${VCS_STATUS_STASHES}" - # 'merge' if the repo is in an unusual state. - [[ -n $VCS_STATUS_ACTION ]] && res+=" ${conflicted}${VCS_STATUS_ACTION}" - # ~42 if have merge conflicts. - (( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}~${VCS_STATUS_NUM_CONFLICTED}" - # +42 if have staged changes. - (( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}+${VCS_STATUS_NUM_STAGED}" - # !42 if have unstaged changes. - (( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}!${VCS_STATUS_NUM_UNSTAGED}" - # ?42 if have untracked files. It's really a question mark, your font isn't broken. - # See POWERLEVEL9K_VCS_UNTRACKED_ICON above if you want to use a different icon. - # Remove the next line if you don't want to see untracked files at all. - (( VCS_STATUS_NUM_UNTRACKED )) && res+=" ${untracked}${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}${VCS_STATUS_NUM_UNTRACKED}" - # "─" if the number of unstaged files is unknown. This can happen due to - # POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY (see below) being set to a non-negative number lower - # than the number of files in the Git index, or due to bash.showDirtyState being set to false - # in the repository config. The number of staged and untracked files may also be unknown - # in this case. - (( VCS_STATUS_HAS_UNSTAGED == -1 )) && res+=" ${modified}─" - - typeset -g my_git_format=$res - } - functions -M my_git_formatter 2>/dev/null - - # Don't count the number of unstaged, untracked and conflicted files in Git repositories with - # more than this many files in the index. Negative value means infinity. - # - # If you are working in Git repositories with tens of millions of files and seeing performance - # sagging, try setting POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY to a number lower than the output - # of `git ls-files | wc -l`. Alternatively, add `bash.showDirtyState = false` to the repository's - # config: `git config bash.showDirtyState false`. - typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1 - - # Don't show Git status in prompt for repositories whose workdir matches this pattern. - # For example, if set to '~', the Git repository at $HOME/.git will be ignored. - # Multiple patterns can be combined with '|': '~(|/foo)|/bar/baz/*'. - typeset -g POWERLEVEL9K_VCS_DISABLED_WORKDIR_PATTERN='~' - - # Disable the default Git status formatting. - typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true - # Install our own Git status formatter. - typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter()))+${my_git_format}}' - # Enable counters for staged, unstaged, etc. - typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1 - - # Custom icon. - # typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_EXPANSION='⭐' - # Custom prefix. - # typeset -g POWERLEVEL9K_VCS_PREFIX='on ' - - # Show status of repositories of these types. You can add svn and/or hg if you are - # using them. If you do, your prompt may become slow even when your current directory - # isn't in an svn or hg repository. - typeset -g POWERLEVEL9K_VCS_BACKENDS=(git) - - ##########################[ status: exit code of the last command ]########################### - # Enable OK_PIPE, ERROR_PIPE and ERROR_SIGNAL status states to allow us to enable, disable and - # style them independently from the regular OK and ERROR state. - typeset -g POWERLEVEL9K_STATUS_EXTENDED_STATES=true - - # Status on success. No content, just an icon. No need to show it if prompt_char is enabled as - # it will signify success by turning green. - typeset -g POWERLEVEL9K_STATUS_OK=true - typeset -g POWERLEVEL9K_STATUS_OK_VISUAL_IDENTIFIER_EXPANSION='✔' - typeset -g POWERLEVEL9K_STATUS_OK_FOREGROUND=2 - typeset -g POWERLEVEL9K_STATUS_OK_BACKGROUND=0 - - # Status when some part of a pipe command fails but the overall exit status is zero. It may look - # like this: 1|0. - typeset -g POWERLEVEL9K_STATUS_OK_PIPE=true - typeset -g POWERLEVEL9K_STATUS_OK_PIPE_VISUAL_IDENTIFIER_EXPANSION='✔' - typeset -g POWERLEVEL9K_STATUS_OK_PIPE_FOREGROUND=2 - typeset -g POWERLEVEL9K_STATUS_OK_PIPE_BACKGROUND=0 - - # Status when it's just an error code (e.g., '1'). No need to show it if prompt_char is enabled as - # it will signify error by turning red. - typeset -g POWERLEVEL9K_STATUS_ERROR=true - typeset -g POWERLEVEL9K_STATUS_ERROR_VISUAL_IDENTIFIER_EXPANSION='✘' - typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND=3 - typeset -g POWERLEVEL9K_STATUS_ERROR_BACKGROUND=1 - - # Status when the last command was terminated by a signal. - typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL=true - # Use terse signal names: "INT" instead of "SIGINT(2)". - typeset -g POWERLEVEL9K_STATUS_VERBOSE_SIGNAME=false - typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_VISUAL_IDENTIFIER_EXPANSION='✘' - typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_FOREGROUND=3 - typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_BACKGROUND=1 - - # Status when some part of a pipe command fails and the overall exit status is also non-zero. - # It may look like this: 1|0. - typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE=true - typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_VISUAL_IDENTIFIER_EXPANSION='✘' - typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_FOREGROUND=3 - typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_BACKGROUND=1 - - ###################[ command_execution_time: duration of the last command ]################### - # Execution time color. - typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=0 - typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_BACKGROUND=3 - # Show duration of the last command if takes at least this many seconds. - typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3 - # Show this many fractional digits. Zero means round to seconds. - typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0 - # Duration format: 1d 2h 3m 4s. - typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s' - # Custom icon. - # typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_VISUAL_IDENTIFIER_EXPANSION='⭐' - # Custom prefix. - # typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PREFIX='took ' - - #######################[ background_jobs: presence of background jobs ]####################### - # Background jobs color. - typeset -g POWERLEVEL9K_BACKGROUND_JOBS_FOREGROUND=6 - typeset -g POWERLEVEL9K_BACKGROUND_JOBS_BACKGROUND=0 - # Don't show the number of background jobs. - typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VERBOSE=false - # Custom icon. - # typeset -g POWERLEVEL9K_BACKGROUND_JOBS_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #######################[ direnv: direnv status (https://direnv.net/) ]######################## - # Direnv color. - typeset -g POWERLEVEL9K_DIRENV_FOREGROUND=3 - typeset -g POWERLEVEL9K_DIRENV_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_DIRENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###############[ asdf: asdf version manager (https://github.com/asdf-vm/asdf) ]############### - # Default asdf color. Only used to display tools for which there is no color override (see below). - # Tip: Override these parameters for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_FOREGROUND and - # POWERLEVEL9K_ASDF_${TOOL}_BACKGROUND. - typeset -g POWERLEVEL9K_ASDF_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_BACKGROUND=7 - - # There are four parameters that can be used to hide asdf tools. Each parameter describes - # conditions under which a tool gets hidden. Parameters can hide tools but not unhide them. If at - # least one parameter decides to hide a tool, that tool gets hidden. If no parameter decides to - # hide a tool, it gets shown. - # - # Special note on the difference between POWERLEVEL9K_ASDF_SOURCES and - # POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW. Consider the effect of the following commands: - # - # asdf local python 3.8.1 - # asdf global python 3.8.1 - # - # After running both commands the current python version is 3.8.1 and its source is "local" as - # it takes precedence over "global". If POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW is set to false, - # it'll hide python version in this case because 3.8.1 is the same as the global version. - # POWERLEVEL9K_ASDF_SOURCES will hide python version only if the value of this parameter doesn't - # contain "local". - - # Hide tool versions that don't come from one of these sources. - # - # Available sources: - # - # - shell `asdf current` says "set by ASDF_${TOOL}_VERSION environment variable" - # - local `asdf current` says "set by /some/not/home/directory/file" - # - global `asdf current` says "set by /home/username/file" - # - # Note: If this parameter is set to (shell local global), it won't hide tools. - # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SOURCES. - typeset -g POWERLEVEL9K_ASDF_SOURCES=(shell local global) - - # If set to false, hide tool versions that are the same as global. - # - # Note: The name of this parameter doesn't reflect its meaning at all. - # Note: If this parameter is set to true, it won't hide tools. - # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_PROMPT_ALWAYS_SHOW. - typeset -g POWERLEVEL9K_ASDF_PROMPT_ALWAYS_SHOW=false - - # If set to false, hide tool versions that are equal to "system". - # - # Note: If this parameter is set to true, it won't hide tools. - # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SHOW_SYSTEM. - typeset -g POWERLEVEL9K_ASDF_SHOW_SYSTEM=true - - # If set to non-empty value, hide tools unless there is a file matching the specified file pattern - # in the current directory, or its parent directory, or its grandparent directory, and so on. - # - # Note: If this parameter is set to empty value, it won't hide tools. - # Note: SHOW_ON_UPGLOB isn't specific to asdf. It works with all prompt segments. - # Tip: Override this parameter for ${TOOL} with POWERLEVEL9K_ASDF_${TOOL}_SHOW_ON_UPGLOB. - # - # Example: Hide nodejs version when there is no package.json and no *.js files in the current - # directory, in `..`, in `../..` and so on. - # - # typeset -g POWERLEVEL9K_ASDF_NODEJS_SHOW_ON_UPGLOB='*.js|package.json' - typeset -g POWERLEVEL9K_ASDF_SHOW_ON_UPGLOB= - - # Ruby version from asdf. - typeset -g POWERLEVEL9K_ASDF_RUBY_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_RUBY_BACKGROUND=1 - # typeset -g POWERLEVEL9K_ASDF_RUBY_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_RUBY_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Python version from asdf. - typeset -g POWERLEVEL9K_ASDF_PYTHON_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_PYTHON_BACKGROUND=4 - # typeset -g POWERLEVEL9K_ASDF_PYTHON_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_PYTHON_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Go version from asdf. - typeset -g POWERLEVEL9K_ASDF_GOLANG_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_GOLANG_BACKGROUND=4 - # typeset -g POWERLEVEL9K_ASDF_GOLANG_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_GOLANG_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Node.js version from asdf. - typeset -g POWERLEVEL9K_ASDF_NODEJS_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_NODEJS_BACKGROUND=2 - # typeset -g POWERLEVEL9K_ASDF_NODEJS_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_NODEJS_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Rust version from asdf. - typeset -g POWERLEVEL9K_ASDF_RUST_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_RUST_BACKGROUND=208 - # typeset -g POWERLEVEL9K_ASDF_RUST_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_RUST_SHOW_ON_UPGLOB='*.foo|*.bar' - - # .NET Core version from asdf. - typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_BACKGROUND=5 - # typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Flutter version from asdf. - typeset -g POWERLEVEL9K_ASDF_FLUTTER_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_FLUTTER_BACKGROUND=4 - # typeset -g POWERLEVEL9K_ASDF_FLUTTER_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_FLUTTER_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Lua version from asdf. - typeset -g POWERLEVEL9K_ASDF_LUA_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_LUA_BACKGROUND=4 - # typeset -g POWERLEVEL9K_ASDF_LUA_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_LUA_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Java version from asdf. - typeset -g POWERLEVEL9K_ASDF_JAVA_FOREGROUND=1 - typeset -g POWERLEVEL9K_ASDF_JAVA_BACKGROUND=7 - # typeset -g POWERLEVEL9K_ASDF_JAVA_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_JAVA_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Perl version from asdf. - typeset -g POWERLEVEL9K_ASDF_PERL_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_PERL_BACKGROUND=4 - # typeset -g POWERLEVEL9K_ASDF_PERL_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_PERL_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Erlang version from asdf. - typeset -g POWERLEVEL9K_ASDF_ERLANG_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_ERLANG_BACKGROUND=1 - # typeset -g POWERLEVEL9K_ASDF_ERLANG_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_ERLANG_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Elixir version from asdf. - typeset -g POWERLEVEL9K_ASDF_ELIXIR_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_ELIXIR_BACKGROUND=5 - # typeset -g POWERLEVEL9K_ASDF_ELIXIR_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_ELIXIR_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Postgres version from asdf. - typeset -g POWERLEVEL9K_ASDF_POSTGRES_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_POSTGRES_BACKGROUND=6 - # typeset -g POWERLEVEL9K_ASDF_POSTGRES_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_POSTGRES_SHOW_ON_UPGLOB='*.foo|*.bar' - - # PHP version from asdf. - typeset -g POWERLEVEL9K_ASDF_PHP_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_PHP_BACKGROUND=5 - # typeset -g POWERLEVEL9K_ASDF_PHP_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_PHP_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Haskell version from asdf. - typeset -g POWERLEVEL9K_ASDF_HASKELL_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_HASKELL_BACKGROUND=3 - # typeset -g POWERLEVEL9K_ASDF_HASKELL_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_HASKELL_SHOW_ON_UPGLOB='*.foo|*.bar' - - # Julia version from asdf. - typeset -g POWERLEVEL9K_ASDF_JULIA_FOREGROUND=0 - typeset -g POWERLEVEL9K_ASDF_JULIA_BACKGROUND=2 - # typeset -g POWERLEVEL9K_ASDF_JULIA_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_ASDF_JULIA_SHOW_ON_UPGLOB='*.foo|*.bar' - - ##########[ nordvpn: nordvpn connection status, linux only (https://nordvpn.com/) ]########### - # NordVPN connection indicator color. - typeset -g POWERLEVEL9K_NORDVPN_FOREGROUND=7 - typeset -g POWERLEVEL9K_NORDVPN_BACKGROUND=4 - # Hide NordVPN connection indicator when not connected. - typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_CONTENT_EXPANSION= - typeset -g POWERLEVEL9K_NORDVPN_{DISCONNECTED,CONNECTING,DISCONNECTING}_VISUAL_IDENTIFIER_EXPANSION= - # Custom icon. - # typeset -g POWERLEVEL9K_NORDVPN_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #################[ ranger: ranger shell (https://github.com/ranger/ranger) ]################## - # Ranger shell color. - typeset -g POWERLEVEL9K_RANGER_FOREGROUND=3 - typeset -g POWERLEVEL9K_RANGER_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_RANGER_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ####################[ yazi: yazi shell (https://github.com/sxyazi/yazi) ]##################### - # Yazi shell color. - typeset -g POWERLEVEL9K_YAZI_FOREGROUND=3 - typeset -g POWERLEVEL9K_YAZI_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_YAZI_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ######################[ nnn: nnn shell (https://github.com/jarun/nnn) ]####################### - # Nnn shell color. - typeset -g POWERLEVEL9K_NNN_FOREGROUND=0 - typeset -g POWERLEVEL9K_NNN_BACKGROUND=6 - # Custom icon. - # typeset -g POWERLEVEL9K_NNN_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ######################[ lf: lf shell (https://github.com/gokcehan/lf) ]####################### - # lf shell color. - typeset -g POWERLEVEL9K_LF_FOREGROUND=0 - typeset -g POWERLEVEL9K_LF_BACKGROUND=6 - # Custom icon. - # typeset -g POWERLEVEL9K_LF_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##################[ xplr: xplr shell (https://github.com/sayanarijit/xplr) ]################## - # xplr shell color. - typeset -g POWERLEVEL9K_XPLR_FOREGROUND=0 - typeset -g POWERLEVEL9K_XPLR_BACKGROUND=6 - # Custom icon. - # typeset -g POWERLEVEL9K_XPLR_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########################[ vim_shell: vim shell indicator (:sh) ]########################### - # Vim shell indicator color. - typeset -g POWERLEVEL9K_VIM_SHELL_FOREGROUND=0 - typeset -g POWERLEVEL9K_VIM_SHELL_BACKGROUND=2 - # Custom icon. - # typeset -g POWERLEVEL9K_VIM_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ######[ midnight_commander: midnight commander shell (https://midnight-commander.org/) ]###### - # Midnight Commander shell color. - typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_FOREGROUND=3 - typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_MIDNIGHT_COMMANDER_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #[ nix_shell: nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html) ]## - # Nix shell color. - typeset -g POWERLEVEL9K_NIX_SHELL_FOREGROUND=0 - typeset -g POWERLEVEL9K_NIX_SHELL_BACKGROUND=4 - - # Display the icon of nix_shell if PATH contains a subdirectory of /nix/store. - # typeset -g POWERLEVEL9K_NIX_SHELL_INFER_FROM_PATH=false - - # Tip: If you want to see just the icon without "pure" and "impure", uncomment the next line. - # typeset -g POWERLEVEL9K_NIX_SHELL_CONTENT_EXPANSION= - - # Custom icon. - # typeset -g POWERLEVEL9K_NIX_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##################[ chezmoi_shell: chezmoi shell (https://www.chezmoi.io/) ]################## - # chezmoi shell color. - typeset -g POWERLEVEL9K_CHEZMOI_SHELL_FOREGROUND=0 - typeset -g POWERLEVEL9K_CHEZMOI_SHELL_BACKGROUND=4 - # Custom icon. - # typeset -g POWERLEVEL9K_CHEZMOI_SHELL_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##################################[ disk_usage: disk usage ]################################## - # Colors for different levels of disk usage. - typeset -g POWERLEVEL9K_DISK_USAGE_NORMAL_FOREGROUND=3 - typeset -g POWERLEVEL9K_DISK_USAGE_NORMAL_BACKGROUND=0 - typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_FOREGROUND=0 - typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_BACKGROUND=3 - typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_FOREGROUND=7 - typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_BACKGROUND=1 - # Thresholds for different levels of disk usage (percentage points). - typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL=90 - typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_LEVEL=95 - # If set to true, hide disk usage when below $POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL percent. - typeset -g POWERLEVEL9K_DISK_USAGE_ONLY_WARNING=false - # Custom icon. - # typeset -g POWERLEVEL9K_DISK_USAGE_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########[ vi_mode: vi mode (you don't need this if you've enabled prompt_char) ]########### - # Foreground color. - typeset -g POWERLEVEL9K_VI_MODE_FOREGROUND=0 - # Text and color for normal (a.k.a. command) vi mode. - typeset -g POWERLEVEL9K_VI_COMMAND_MODE_STRING=NORMAL - typeset -g POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=2 - # Text and color for visual vi mode. - typeset -g POWERLEVEL9K_VI_VISUAL_MODE_STRING=VISUAL - typeset -g POWERLEVEL9K_VI_MODE_VISUAL_BACKGROUND=4 - # Text and color for overtype (a.k.a. overwrite and replace) vi mode. - typeset -g POWERLEVEL9K_VI_OVERWRITE_MODE_STRING=OVERTYPE - typeset -g POWERLEVEL9K_VI_MODE_OVERWRITE_BACKGROUND=3 - # Text and color for insert vi mode. - typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING= - typeset -g POWERLEVEL9K_VI_MODE_INSERT_FOREGROUND=8 - # Custom icon. - # typeset -g POWERLEVEL9K_VI_MODE_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ######################################[ ram: free RAM ]####################################### - # RAM color. - typeset -g POWERLEVEL9K_RAM_FOREGROUND=0 - typeset -g POWERLEVEL9K_RAM_BACKGROUND=3 - # Custom icon. - # typeset -g POWERLEVEL9K_RAM_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #####################################[ swap: used swap ]###################################### - # Swap color. - typeset -g POWERLEVEL9K_SWAP_FOREGROUND=0 - typeset -g POWERLEVEL9K_SWAP_BACKGROUND=3 - # Custom icon. - # typeset -g POWERLEVEL9K_SWAP_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ######################################[ load: CPU load ]###################################### - # Show average CPU load over this many last minutes. Valid values are 1, 5 and 15. - typeset -g POWERLEVEL9K_LOAD_WHICH=5 - # Load color when load is under 50%. - typeset -g POWERLEVEL9K_LOAD_NORMAL_FOREGROUND=0 - typeset -g POWERLEVEL9K_LOAD_NORMAL_BACKGROUND=2 - # Load color when load is between 50% and 70%. - typeset -g POWERLEVEL9K_LOAD_WARNING_FOREGROUND=0 - typeset -g POWERLEVEL9K_LOAD_WARNING_BACKGROUND=3 - # Load color when load is over 70%. - typeset -g POWERLEVEL9K_LOAD_CRITICAL_FOREGROUND=0 - typeset -g POWERLEVEL9K_LOAD_CRITICAL_BACKGROUND=1 - # Custom icon. - # typeset -g POWERLEVEL9K_LOAD_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################[ todo: todo items (https://github.com/todotxt/todo.txt-cli) ]################ - # Todo color. - typeset -g POWERLEVEL9K_TODO_FOREGROUND=0 - typeset -g POWERLEVEL9K_TODO_BACKGROUND=8 - # Hide todo when the total number of tasks is zero. - typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_TOTAL=true - # Hide todo when the number of tasks after filtering is zero. - typeset -g POWERLEVEL9K_TODO_HIDE_ZERO_FILTERED=false - - # Todo format. The following parameters are available within the expansion. - # - # - P9K_TODO_TOTAL_TASK_COUNT The total number of tasks. - # - P9K_TODO_FILTERED_TASK_COUNT The number of tasks after filtering. - # - # These variables correspond to the last line of the output of `todo.sh -p ls`: - # - # TODO: 24 of 42 tasks shown - # - # Here 24 is P9K_TODO_FILTERED_TASK_COUNT and 42 is P9K_TODO_TOTAL_TASK_COUNT. - # - # typeset -g POWERLEVEL9K_TODO_CONTENT_EXPANSION='$P9K_TODO_FILTERED_TASK_COUNT' - - # Custom icon. - # typeset -g POWERLEVEL9K_TODO_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########[ timewarrior: timewarrior tracking status (https://timewarrior.net/) ]############ - # Timewarrior color. - typeset -g POWERLEVEL9K_TIMEWARRIOR_FOREGROUND=255 - typeset -g POWERLEVEL9K_TIMEWARRIOR_BACKGROUND=8 - - # If the tracked task is longer than 24 characters, truncate and append "…". - # Tip: To always display tasks without truncation, delete the following parameter. - # Tip: To hide task names and display just the icon when time tracking is enabled, set the - # value of the following parameter to "". - typeset -g POWERLEVEL9K_TIMEWARRIOR_CONTENT_EXPANSION='${P9K_CONTENT:0:24}${${P9K_CONTENT:24}:+…}' - - # Custom icon. - # typeset -g POWERLEVEL9K_TIMEWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##############[ taskwarrior: taskwarrior task count (https://taskwarrior.org/) ]############## - # Taskwarrior color. - typeset -g POWERLEVEL9K_TASKWARRIOR_FOREGROUND=0 - typeset -g POWERLEVEL9K_TASKWARRIOR_BACKGROUND=6 - - # Taskwarrior segment format. The following parameters are available within the expansion. - # - # - P9K_TASKWARRIOR_PENDING_COUNT The number of pending tasks: `task +PENDING count`. - # - P9K_TASKWARRIOR_OVERDUE_COUNT The number of overdue tasks: `task +OVERDUE count`. - # - # Zero values are represented as empty parameters. - # - # The default format: - # - # '${P9K_TASKWARRIOR_OVERDUE_COUNT:+"!$P9K_TASKWARRIOR_OVERDUE_COUNT/"}$P9K_TASKWARRIOR_PENDING_COUNT' - # - # typeset -g POWERLEVEL9K_TASKWARRIOR_CONTENT_EXPANSION='$P9K_TASKWARRIOR_PENDING_COUNT' - - # Custom icon. - # typeset -g POWERLEVEL9K_TASKWARRIOR_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ######[ per_directory_history: Oh My Zsh per-directory-history local/global indicator ]####### - # Color when using local/global history. - typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_FOREGROUND=0 - typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_BACKGROUND=5 - typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_FOREGROUND=0 - typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_BACKGROUND=3 - - # Tip: Uncomment the next two lines to hide "local"/"global" text and leave just the icon. - # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_CONTENT_EXPANSION='' - # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_CONTENT_EXPANSION='' - - # Custom icon. - # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_LOCAL_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_PER_DIRECTORY_HISTORY_GLOBAL_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################################[ cpu_arch: CPU architecture ]################################ - # CPU architecture color. - typeset -g POWERLEVEL9K_CPU_ARCH_FOREGROUND=0 - typeset -g POWERLEVEL9K_CPU_ARCH_BACKGROUND=3 - - # Hide the segment when on a specific CPU architecture. - # typeset -g POWERLEVEL9K_CPU_ARCH_X86_64_CONTENT_EXPANSION= - # typeset -g POWERLEVEL9K_CPU_ARCH_X86_64_VISUAL_IDENTIFIER_EXPANSION= - - # Custom icon. - # typeset -g POWERLEVEL9K_CPU_ARCH_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##################################[ context: user@hostname ]################################## - # Context color when running with privileges. - typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=1 - typeset -g POWERLEVEL9K_CONTEXT_ROOT_BACKGROUND=0 - # Context color in SSH without privileges. - typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=3 - typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_BACKGROUND=0 - # Default context color (no privileges, no SSH). - typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=3 - typeset -g POWERLEVEL9K_CONTEXT_BACKGROUND=0 - - # Context format when running with privileges: user@hostname. - typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%n@%m' - # Context format when in SSH without privileges: user@hostname. - typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m' - # Default context format (no privileges, no SSH): user@hostname. - typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n@%m' - - # Don't show context unless running with privileges or in SSH. - # Tip: Remove the next line to always show context. - typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_{CONTENT,VISUAL_IDENTIFIER}_EXPANSION= - - # Custom icon. - # typeset -g POWERLEVEL9K_CONTEXT_VISUAL_IDENTIFIER_EXPANSION='⭐' - # Custom prefix. - # typeset -g POWERLEVEL9K_CONTEXT_PREFIX='with ' - - ###[ virtualenv: python virtual environment (https://docs.python.org/3/library/venv.html) ]### - # Python virtual environment color. - typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_VIRTUALENV_BACKGROUND=4 - # Don't show Python version next to the virtual environment name. - typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false - # If set to "false", won't show virtualenv if pyenv is already shown. - # If set to "if-different", won't show virtualenv if it's the same as pyenv. - typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_WITH_PYENV=false - # Separate environment name from Python version only with a space. - typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER= - # Custom icon. - # typeset -g POWERLEVEL9K_VIRTUALENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #####################[ anaconda: conda environment (https://conda.io/) ]###################### - # Anaconda environment color. - typeset -g POWERLEVEL9K_ANACONDA_FOREGROUND=0 - typeset -g POWERLEVEL9K_ANACONDA_BACKGROUND=4 - - # Anaconda segment format. The following parameters are available within the expansion. - # - # - CONDA_PREFIX Absolute path to the active Anaconda/Miniconda environment. - # - CONDA_DEFAULT_ENV Name of the active Anaconda/Miniconda environment. - # - CONDA_PROMPT_MODIFIER Configurable prompt modifier (see below). - # - P9K_ANACONDA_PYTHON_VERSION Current python version (python --version). - # - # CONDA_PROMPT_MODIFIER can be configured with the following command: - # - # conda config --set env_prompt '({default_env}) ' - # - # The last argument is a Python format string that can use the following variables: - # - # - prefix The same as CONDA_PREFIX. - # - default_env The same as CONDA_DEFAULT_ENV. - # - name The last segment of CONDA_PREFIX. - # - stacked_env Comma-separated list of names in the environment stack. The first element is - # always the same as default_env. - # - # Note: '({default_env}) ' is the default value of env_prompt. - # - # The default value of POWERLEVEL9K_ANACONDA_CONTENT_EXPANSION expands to $CONDA_PROMPT_MODIFIER - # without the surrounding parentheses, or to the last path component of CONDA_PREFIX if the former - # is empty. - typeset -g POWERLEVEL9K_ANACONDA_CONTENT_EXPANSION='${${${${CONDA_PROMPT_MODIFIER#\(}% }%\)}:-${CONDA_PREFIX:t}}' - - # Custom icon. - # typeset -g POWERLEVEL9K_ANACONDA_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################[ pyenv: python environment (https://github.com/pyenv/pyenv) ]################ - # Pyenv color. - typeset -g POWERLEVEL9K_PYENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_PYENV_BACKGROUND=4 - # Hide python version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_PYENV_SOURCES=(shell local global) - # If set to false, hide python version if it's the same as global: - # $(pyenv version-name) == $(pyenv global). - typeset -g POWERLEVEL9K_PYENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide python version if it's equal to "system". - typeset -g POWERLEVEL9K_PYENV_SHOW_SYSTEM=true - - # Pyenv segment format. The following parameters are available within the expansion. - # - # - P9K_CONTENT Current pyenv environment (pyenv version-name). - # - P9K_PYENV_PYTHON_VERSION Current python version (python --version). - # - # The default format has the following logic: - # - # 1. Display just "$P9K_CONTENT" if it's equal to "$P9K_PYENV_PYTHON_VERSION" or - # starts with "$P9K_PYENV_PYTHON_VERSION/". - # 2. Otherwise display "$P9K_CONTENT $P9K_PYENV_PYTHON_VERSION". - typeset -g POWERLEVEL9K_PYENV_CONTENT_EXPANSION='${P9K_CONTENT}${${P9K_CONTENT:#$P9K_PYENV_PYTHON_VERSION(|/*)}:+ $P9K_PYENV_PYTHON_VERSION}' - - # Custom icon. - # typeset -g POWERLEVEL9K_PYENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################[ goenv: go environment (https://github.com/syndbg/goenv) ]################ - # Goenv color. - typeset -g POWERLEVEL9K_GOENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_GOENV_BACKGROUND=4 - # Hide go version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_GOENV_SOURCES=(shell local global) - # If set to false, hide go version if it's the same as global: - # $(goenv version-name) == $(goenv global). - typeset -g POWERLEVEL9K_GOENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide go version if it's equal to "system". - typeset -g POWERLEVEL9K_GOENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_GOENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##########[ nodenv: node.js version from nodenv (https://github.com/nodenv/nodenv) ]########## - # Nodenv color. - typeset -g POWERLEVEL9K_NODENV_FOREGROUND=2 - typeset -g POWERLEVEL9K_NODENV_BACKGROUND=0 - # Hide node version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_NODENV_SOURCES=(shell local global) - # If set to false, hide node version if it's the same as global: - # $(nodenv version-name) == $(nodenv global). - typeset -g POWERLEVEL9K_NODENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide node version if it's equal to "system". - typeset -g POWERLEVEL9K_NODENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_NODENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##############[ nvm: node.js version from nvm (https://github.com/nvm-sh/nvm) ]############### - # Nvm color. - typeset -g POWERLEVEL9K_NVM_FOREGROUND=0 - typeset -g POWERLEVEL9K_NVM_BACKGROUND=5 - # If set to false, hide node version if it's the same as default: - # $(nvm version current) == $(nvm version default). - typeset -g POWERLEVEL9K_NVM_PROMPT_ALWAYS_SHOW=false - # If set to false, hide node version if it's equal to "system". - typeset -g POWERLEVEL9K_NVM_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_NVM_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ############[ nodeenv: node.js environment (https://github.com/ekalinin/nodeenv) ]############ - # Nodeenv color. - typeset -g POWERLEVEL9K_NODEENV_FOREGROUND=2 - typeset -g POWERLEVEL9K_NODEENV_BACKGROUND=0 - # Don't show Node version next to the environment name. - typeset -g POWERLEVEL9K_NODEENV_SHOW_NODE_VERSION=false - # Separate environment name from Node version only with a space. - typeset -g POWERLEVEL9K_NODEENV_{LEFT,RIGHT}_DELIMITER= - # Custom icon. - # typeset -g POWERLEVEL9K_NODEENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##############################[ node_version: node.js version ]############################### - # Node version color. - typeset -g POWERLEVEL9K_NODE_VERSION_FOREGROUND=7 - typeset -g POWERLEVEL9K_NODE_VERSION_BACKGROUND=2 - # Show node version only when in a directory tree containing package.json. - typeset -g POWERLEVEL9K_NODE_VERSION_PROJECT_ONLY=true - # Custom icon. - # typeset -g POWERLEVEL9K_NODE_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #######################[ go_version: go version (https://golang.org) ]######################## - # Go version color. - typeset -g POWERLEVEL9K_GO_VERSION_FOREGROUND=255 - typeset -g POWERLEVEL9K_GO_VERSION_BACKGROUND=2 - # Show go version only when in a go project subdirectory. - typeset -g POWERLEVEL9K_GO_VERSION_PROJECT_ONLY=true - # Custom icon. - # typeset -g POWERLEVEL9K_GO_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #################[ rust_version: rustc version (https://www.rust-lang.org) ]################## - # Rust version color. - typeset -g POWERLEVEL9K_RUST_VERSION_FOREGROUND=0 - typeset -g POWERLEVEL9K_RUST_VERSION_BACKGROUND=208 - # Show rust version only when in a rust project subdirectory. - typeset -g POWERLEVEL9K_RUST_VERSION_PROJECT_ONLY=true - # Custom icon. - # typeset -g POWERLEVEL9K_RUST_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###############[ dotnet_version: .NET version (https://dotnet.microsoft.com) ]################ - # .NET version color. - typeset -g POWERLEVEL9K_DOTNET_VERSION_FOREGROUND=7 - typeset -g POWERLEVEL9K_DOTNET_VERSION_BACKGROUND=5 - # Show .NET version only when in a .NET project subdirectory. - typeset -g POWERLEVEL9K_DOTNET_VERSION_PROJECT_ONLY=true - # Custom icon. - # typeset -g POWERLEVEL9K_DOTNET_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #####################[ php_version: php version (https://www.php.net/) ]###################### - # PHP version color. - typeset -g POWERLEVEL9K_PHP_VERSION_FOREGROUND=0 - typeset -g POWERLEVEL9K_PHP_VERSION_BACKGROUND=5 - # Show PHP version only when in a PHP project subdirectory. - typeset -g POWERLEVEL9K_PHP_VERSION_PROJECT_ONLY=true - # Custom icon. - # typeset -g POWERLEVEL9K_PHP_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##########[ laravel_version: laravel php framework version (https://laravel.com/) ]########### - # Laravel version color. - typeset -g POWERLEVEL9K_LARAVEL_VERSION_FOREGROUND=1 - typeset -g POWERLEVEL9K_LARAVEL_VERSION_BACKGROUND=7 - # Custom icon. - # typeset -g POWERLEVEL9K_LARAVEL_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #############[ rbenv: ruby version from rbenv (https://github.com/rbenv/rbenv) ]############## - # Rbenv color. - typeset -g POWERLEVEL9K_RBENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_RBENV_BACKGROUND=1 - # Hide ruby version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_RBENV_SOURCES=(shell local global) - # If set to false, hide ruby version if it's the same as global: - # $(rbenv version-name) == $(rbenv global). - typeset -g POWERLEVEL9K_RBENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide ruby version if it's equal to "system". - typeset -g POWERLEVEL9K_RBENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_RBENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ####################[ java_version: java version (https://www.java.com/) ]#################### - # Java version color. - typeset -g POWERLEVEL9K_JAVA_VERSION_FOREGROUND=1 - typeset -g POWERLEVEL9K_JAVA_VERSION_BACKGROUND=7 - # Show java version only when in a java project subdirectory. - typeset -g POWERLEVEL9K_JAVA_VERSION_PROJECT_ONLY=true - # Show brief version. - typeset -g POWERLEVEL9K_JAVA_VERSION_FULL=false - # Custom icon. - # typeset -g POWERLEVEL9K_JAVA_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###[ package: name@version from package.json (https://docs.npmjs.com/files/package.json) ]#### - # Package color. - typeset -g POWERLEVEL9K_PACKAGE_FOREGROUND=0 - typeset -g POWERLEVEL9K_PACKAGE_BACKGROUND=6 - - # Package format. The following parameters are available within the expansion. - # - # - P9K_PACKAGE_NAME The value of `name` field in package.json. - # - P9K_PACKAGE_VERSION The value of `version` field in package.json. - # - # typeset -g POWERLEVEL9K_PACKAGE_CONTENT_EXPANSION='${P9K_PACKAGE_NAME//\%/%%}@${P9K_PACKAGE_VERSION//\%/%%}' - - # Custom icon. - # typeset -g POWERLEVEL9K_PACKAGE_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #######################[ rvm: ruby version from rvm (https://rvm.io) ]######################## - # Rvm color. - typeset -g POWERLEVEL9K_RVM_FOREGROUND=0 - typeset -g POWERLEVEL9K_RVM_BACKGROUND=240 - # Don't show @gemset at the end. - typeset -g POWERLEVEL9K_RVM_SHOW_GEMSET=false - # Don't show ruby- at the front. - typeset -g POWERLEVEL9K_RVM_SHOW_PREFIX=false - # Custom icon. - # typeset -g POWERLEVEL9K_RVM_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########[ fvm: flutter version management (https://github.com/leoafarias/fvm) ]############ - # Fvm color. - typeset -g POWERLEVEL9K_FVM_FOREGROUND=0 - typeset -g POWERLEVEL9K_FVM_BACKGROUND=4 - # Custom icon. - # typeset -g POWERLEVEL9K_FVM_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##########[ luaenv: lua version from luaenv (https://github.com/cehoffman/luaenv) ]########### - # Lua color. - typeset -g POWERLEVEL9K_LUAENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_LUAENV_BACKGROUND=4 - # Hide lua version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_LUAENV_SOURCES=(shell local global) - # If set to false, hide lua version if it's the same as global: - # $(luaenv version-name) == $(luaenv global). - typeset -g POWERLEVEL9K_LUAENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide lua version if it's equal to "system". - typeset -g POWERLEVEL9K_LUAENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_LUAENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###############[ jenv: java version from jenv (https://github.com/jenv/jenv) ]################ - # Java color. - typeset -g POWERLEVEL9K_JENV_FOREGROUND=1 - typeset -g POWERLEVEL9K_JENV_BACKGROUND=7 - # Hide java version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_JENV_SOURCES=(shell local global) - # If set to false, hide java version if it's the same as global: - # $(jenv version-name) == $(jenv global). - typeset -g POWERLEVEL9K_JENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide java version if it's equal to "system". - typeset -g POWERLEVEL9K_JENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_JENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########[ plenv: perl version from plenv (https://github.com/tokuhirom/plenv) ]############ - # Perl color. - typeset -g POWERLEVEL9K_PLENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_PLENV_BACKGROUND=4 - # Hide perl version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_PLENV_SOURCES=(shell local global) - # If set to false, hide perl version if it's the same as global: - # $(plenv version-name) == $(plenv global). - typeset -g POWERLEVEL9K_PLENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide perl version if it's equal to "system". - typeset -g POWERLEVEL9K_PLENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_PLENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########[ perlbrew: perl version from perlbrew (https://github.com/gugod/App-perlbrew) ]############ - # Perlbrew color. - typeset -g POWERLEVEL9K_PERLBREW_FOREGROUND=67 - # Show perlbrew version only when in a perl project subdirectory. - typeset -g POWERLEVEL9K_PERLBREW_PROJECT_ONLY=true - # Don't show "perl-" at the front. - typeset -g POWERLEVEL9K_PERLBREW_SHOW_PREFIX=false - # Custom icon. - # typeset -g POWERLEVEL9K_PERLBREW_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ############[ phpenv: php version from phpenv (https://github.com/phpenv/phpenv) ]############ - # PHP color. - typeset -g POWERLEVEL9K_PHPENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_PHPENV_BACKGROUND=5 - # Hide php version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_PHPENV_SOURCES=(shell local global) - # If set to false, hide php version if it's the same as global: - # $(phpenv version-name) == $(phpenv global). - typeset -g POWERLEVEL9K_PHPENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide PHP version if it's equal to "system". - typeset -g POWERLEVEL9K_PHPENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_PHPENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #######[ scalaenv: scala version from scalaenv (https://github.com/scalaenv/scalaenv) ]####### - # Scala color. - typeset -g POWERLEVEL9K_SCALAENV_FOREGROUND=0 - typeset -g POWERLEVEL9K_SCALAENV_BACKGROUND=1 - # Hide scala version if it doesn't come from one of these sources. - typeset -g POWERLEVEL9K_SCALAENV_SOURCES=(shell local global) - # If set to false, hide scala version if it's the same as global: - # $(scalaenv version-name) == $(scalaenv global). - typeset -g POWERLEVEL9K_SCALAENV_PROMPT_ALWAYS_SHOW=false - # If set to false, hide scala version if it's equal to "system". - typeset -g POWERLEVEL9K_SCALAENV_SHOW_SYSTEM=true - # Custom icon. - # typeset -g POWERLEVEL9K_SCALAENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##########[ haskell_stack: haskell version from stack (https://haskellstack.org/) ]########### - # Haskell color. - typeset -g POWERLEVEL9K_HASKELL_STACK_FOREGROUND=0 - typeset -g POWERLEVEL9K_HASKELL_STACK_BACKGROUND=3 - - # Hide haskell version if it doesn't come from one of these sources. - # - # shell: version is set by STACK_YAML - # local: version is set by stack.yaml up the directory tree - # global: version is set by the implicit global project (~/.stack/global-project/stack.yaml) - typeset -g POWERLEVEL9K_HASKELL_STACK_SOURCES=(shell local) - # If set to false, hide haskell version if it's the same as in the implicit global project. - typeset -g POWERLEVEL9K_HASKELL_STACK_ALWAYS_SHOW=true - # Custom icon. - # typeset -g POWERLEVEL9K_HASKELL_STACK_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################[ terraform: terraform workspace (https://www.terraform.io) ]################# - # Don't show terraform workspace if it's literally "default". - typeset -g POWERLEVEL9K_TERRAFORM_SHOW_DEFAULT=false - # POWERLEVEL9K_TERRAFORM_CLASSES is an array with even number of elements. The first element - # in each pair defines a pattern against which the current terraform workspace gets matched. - # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) - # that gets matched. If you unset all POWERLEVEL9K_TERRAFORM_*CONTENT_EXPANSION parameters, - # you'll see this value in your prompt. The second element of each pair in - # POWERLEVEL9K_TERRAFORM_CLASSES defines the workspace class. Patterns are tried in order. The - # first match wins. - # - # For example, given these settings: - # - # typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=( - # '*prod*' PROD - # '*test*' TEST - # '*' OTHER) - # - # If your current terraform workspace is "project_test", its class is TEST because "project_test" - # doesn't match the pattern '*prod*' but does match '*test*'. - # - # You can define different colors, icons and content expansions for different classes: - # - # typeset -g POWERLEVEL9K_TERRAFORM_TEST_FOREGROUND=2 - # typeset -g POWERLEVEL9K_TERRAFORM_TEST_BACKGROUND=0 - # typeset -g POWERLEVEL9K_TERRAFORM_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_TERRAFORM_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' - typeset -g POWERLEVEL9K_TERRAFORM_CLASSES=( - # '*prod*' PROD # These values are examples that are unlikely - # '*test*' TEST # to match your needs. Customize them as needed. - '*' OTHER) - typeset -g POWERLEVEL9K_TERRAFORM_OTHER_FOREGROUND=4 - typeset -g POWERLEVEL9K_TERRAFORM_OTHER_BACKGROUND=0 - # typeset -g POWERLEVEL9K_TERRAFORM_OTHER_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #############[ terraform_version: terraform version (https://www.terraform.io) ]############## - # Terraform version color. - typeset -g POWERLEVEL9K_TERRAFORM_VERSION_FOREGROUND=4 - typeset -g POWERLEVEL9K_TERRAFORM_VERSION_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_TERRAFORM_VERSION_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################[ terraform_version: It shows active terraform version (https://www.terraform.io) ]################# - typeset -g POWERLEVEL9K_TERRAFORM_VERSION_SHOW_ON_COMMAND='terraform|tf' - - #############[ kubecontext: current kubernetes context (https://kubernetes.io/) ]############# - # Show kubecontext only when the command you are typing invokes one of these tools. - # Tip: Remove the next line to always show kubecontext. - typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|flux|fluxctl|stern|kubeseal|skaffold|kubent|kubecolor|cmctl|sparkctl' - - # Kubernetes context classes for the purpose of using different colors, icons and expansions with - # different contexts. - # - # POWERLEVEL9K_KUBECONTEXT_CLASSES is an array with even number of elements. The first element - # in each pair defines a pattern against which the current kubernetes context gets matched. - # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) - # that gets matched. If you unset all POWERLEVEL9K_KUBECONTEXT_*CONTENT_EXPANSION parameters, - # you'll see this value in your prompt. The second element of each pair in - # POWERLEVEL9K_KUBECONTEXT_CLASSES defines the context class. Patterns are tried in order. The - # first match wins. - # - # For example, given these settings: - # - # typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=( - # '*prod*' PROD - # '*test*' TEST - # '*' DEFAULT) - # - # If your current kubernetes context is "deathray-testing/default", its class is TEST - # because "deathray-testing/default" doesn't match the pattern '*prod*' but does match '*test*'. - # - # You can define different colors, icons and content expansions for different classes: - # - # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_FOREGROUND=0 - # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_BACKGROUND=2 - # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_KUBECONTEXT_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' - typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=( - # '*prod*' PROD # These values are examples that are unlikely - # '*test*' TEST # to match your needs. Customize them as needed. - '*' DEFAULT) - typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=7 - typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_BACKGROUND=5 - # typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' - - # Use POWERLEVEL9K_KUBECONTEXT_CONTENT_EXPANSION to specify the content displayed by kubecontext - # segment. Parameter expansions are very flexible and fast, too. See reference: - # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion. - # - # Within the expansion the following parameters are always available: - # - # - P9K_CONTENT The content that would've been displayed if there was no content - # expansion defined. - # - P9K_KUBECONTEXT_NAME The current context's name. Corresponds to column NAME in the - # output of `kubectl config get-contexts`. - # - P9K_KUBECONTEXT_CLUSTER The current context's cluster. Corresponds to column CLUSTER in the - # output of `kubectl config get-contexts`. - # - P9K_KUBECONTEXT_NAMESPACE The current context's namespace. Corresponds to column NAMESPACE - # in the output of `kubectl config get-contexts`. If there is no - # namespace, the parameter is set to "default". - # - P9K_KUBECONTEXT_USER The current context's user. Corresponds to column AUTHINFO in the - # output of `kubectl config get-contexts`. - # - # If the context points to Google Kubernetes Engine (GKE) or Elastic Kubernetes Service (EKS), - # the following extra parameters are available: - # - # - P9K_KUBECONTEXT_CLOUD_NAME Either "gke" or "eks". - # - P9K_KUBECONTEXT_CLOUD_ACCOUNT Account/project ID. - # - P9K_KUBECONTEXT_CLOUD_ZONE Availability zone. - # - P9K_KUBECONTEXT_CLOUD_CLUSTER Cluster. - # - # P9K_KUBECONTEXT_CLOUD_* parameters are derived from P9K_KUBECONTEXT_CLUSTER. For example, - # if P9K_KUBECONTEXT_CLUSTER is "gke_my-account_us-east1-a_my-cluster-01": - # - # - P9K_KUBECONTEXT_CLOUD_NAME=gke - # - P9K_KUBECONTEXT_CLOUD_ACCOUNT=my-account - # - P9K_KUBECONTEXT_CLOUD_ZONE=us-east1-a - # - P9K_KUBECONTEXT_CLOUD_CLUSTER=my-cluster-01 - # - # If P9K_KUBECONTEXT_CLUSTER is "arn:aws:eks:us-east-1:123456789012:cluster/my-cluster-01": - # - # - P9K_KUBECONTEXT_CLOUD_NAME=eks - # - P9K_KUBECONTEXT_CLOUD_ACCOUNT=123456789012 - # - P9K_KUBECONTEXT_CLOUD_ZONE=us-east-1 - # - P9K_KUBECONTEXT_CLOUD_CLUSTER=my-cluster-01 - typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION= - # Show P9K_KUBECONTEXT_CLOUD_CLUSTER if it's not empty and fall back to P9K_KUBECONTEXT_NAME. - POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${P9K_KUBECONTEXT_CLOUD_CLUSTER:-${P9K_KUBECONTEXT_NAME}}' - # Append the current context's namespace if it's not "default". - POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default}' - - # Custom prefix. - # typeset -g POWERLEVEL9K_KUBECONTEXT_PREFIX='at ' - - #[ aws: aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) ]# - # Show aws only when the command you are typing invokes one of these tools. - # Tip: Remove the next line to always show aws. - typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|cdk|terraform|pulumi|terragrunt' - - # POWERLEVEL9K_AWS_CLASSES is an array with even number of elements. The first element - # in each pair defines a pattern against which the current AWS profile gets matched. - # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) - # that gets matched. If you unset all POWERLEVEL9K_AWS_*CONTENT_EXPANSION parameters, - # you'll see this value in your prompt. The second element of each pair in - # POWERLEVEL9K_AWS_CLASSES defines the profile class. Patterns are tried in order. The - # first match wins. - # - # For example, given these settings: - # - # typeset -g POWERLEVEL9K_AWS_CLASSES=( - # '*prod*' PROD - # '*test*' TEST - # '*' DEFAULT) - # - # If your current AWS profile is "company_test", its class is TEST - # because "company_test" doesn't match the pattern '*prod*' but does match '*test*'. - # - # You can define different colors, icons and content expansions for different classes: - # - # typeset -g POWERLEVEL9K_AWS_TEST_FOREGROUND=28 - # typeset -g POWERLEVEL9K_AWS_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_AWS_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' - typeset -g POWERLEVEL9K_AWS_CLASSES=( - # '*prod*' PROD # These values are examples that are unlikely - # '*test*' TEST # to match your needs. Customize them as needed. - '*' DEFAULT) - typeset -g POWERLEVEL9K_AWS_DEFAULT_FOREGROUND=7 - typeset -g POWERLEVEL9K_AWS_DEFAULT_BACKGROUND=1 - # typeset -g POWERLEVEL9K_AWS_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' - - # AWS segment format. The following parameters are available within the expansion. - # - # - P9K_AWS_PROFILE The name of the current AWS profile. - # - P9K_AWS_REGION The region associated with the current AWS profile. - typeset -g POWERLEVEL9K_AWS_CONTENT_EXPANSION='${P9K_AWS_PROFILE//\%/%%}${P9K_AWS_REGION:+ ${P9K_AWS_REGION//\%/%%}}' - - #[ aws_eb_env: aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/) ]# - # AWS Elastic Beanstalk environment color. - typeset -g POWERLEVEL9K_AWS_EB_ENV_FOREGROUND=2 - typeset -g POWERLEVEL9K_AWS_EB_ENV_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_AWS_EB_ENV_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##########[ azure: azure account name (https://docs.microsoft.com/en-us/cli/azure) ]########## - # Show azure only when the command you are typing invokes one of these tools. - # Tip: Remove the next line to always show azure. - typeset -g POWERLEVEL9K_AZURE_SHOW_ON_COMMAND='az|terraform|pulumi|terragrunt' - - # POWERLEVEL9K_AZURE_CLASSES is an array with even number of elements. The first element - # in each pair defines a pattern against which the current azure account name gets matched. - # More specifically, it's P9K_CONTENT prior to the application of context expansion (see below) - # that gets matched. If you unset all POWERLEVEL9K_AZURE_*CONTENT_EXPANSION parameters, - # you'll see this value in your prompt. The second element of each pair in - # POWERLEVEL9K_AZURE_CLASSES defines the account class. Patterns are tried in order. The - # first match wins. - # - # For example, given these settings: - # - # typeset -g POWERLEVEL9K_AZURE_CLASSES=( - # '*prod*' PROD - # '*test*' TEST - # '*' OTHER) - # - # If your current azure account is "company_test", its class is TEST because "company_test" - # doesn't match the pattern '*prod*' but does match '*test*'. - # - # You can define different colors, icons and content expansions for different classes: - # - # typeset -g POWERLEVEL9K_AZURE_TEST_FOREGROUND=2 - # typeset -g POWERLEVEL9K_AZURE_TEST_BACKGROUND=0 - # typeset -g POWERLEVEL9K_AZURE_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_AZURE_TEST_CONTENT_EXPANSION='> ${P9K_CONTENT} <' - typeset -g POWERLEVEL9K_AZURE_CLASSES=( - # '*prod*' PROD # These values are examples that are unlikely - # '*test*' TEST # to match your needs. Customize them as needed. - '*' OTHER) - - # Azure account name color. - typeset -g POWERLEVEL9K_AZURE_OTHER_FOREGROUND=7 - typeset -g POWERLEVEL9K_AZURE_OTHER_BACKGROUND=4 - # Custom icon. - # typeset -g POWERLEVEL9K_AZURE_OTHER_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ##########[ gcloud: google cloud account and project (https://cloud.google.com/) ]########### - # Show gcloud only when the command you are typing invokes one of these tools. - # Tip: Remove the next line to always show gcloud. - typeset -g POWERLEVEL9K_GCLOUD_SHOW_ON_COMMAND='gcloud|gcs|gsutil' - # Google cloud color. - typeset -g POWERLEVEL9K_GCLOUD_FOREGROUND=7 - typeset -g POWERLEVEL9K_GCLOUD_BACKGROUND=4 - - # Google cloud format. Change the value of POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION and/or - # POWERLEVEL9K_GCLOUD_COMPLETE_CONTENT_EXPANSION if the default is too verbose or not informative - # enough. You can use the following parameters in the expansions. Each of them corresponds to the - # output of `gcloud` tool. - # - # Parameter | Source - # -------------------------|-------------------------------------------------------------------- - # P9K_GCLOUD_CONFIGURATION | gcloud config configurations list --format='value(name)' - # P9K_GCLOUD_ACCOUNT | gcloud config get-value account - # P9K_GCLOUD_PROJECT_ID | gcloud config get-value project - # P9K_GCLOUD_PROJECT_NAME | gcloud projects describe $P9K_GCLOUD_PROJECT_ID --format='value(name)' - # - # Note: ${VARIABLE//\%/%%} expands to ${VARIABLE} with all occurrences of '%' replaced with '%%'. - # - # Obtaining project name requires sending a request to Google servers. This can take a long time - # and even fail. When project name is unknown, P9K_GCLOUD_PROJECT_NAME is not set and gcloud - # prompt segment is in state PARTIAL. When project name gets known, P9K_GCLOUD_PROJECT_NAME gets - # set and gcloud prompt segment transitions to state COMPLETE. - # - # You can customize the format, icon and colors of gcloud segment separately for states PARTIAL - # and COMPLETE. You can also hide gcloud in state PARTIAL by setting - # POWERLEVEL9K_GCLOUD_PARTIAL_VISUAL_IDENTIFIER_EXPANSION and - # POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION to empty. - typeset -g POWERLEVEL9K_GCLOUD_PARTIAL_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT_ID//\%/%%}' - typeset -g POWERLEVEL9K_GCLOUD_COMPLETE_CONTENT_EXPANSION='${P9K_GCLOUD_PROJECT_NAME//\%/%%}' - - # Send a request to Google (by means of `gcloud projects describe ...`) to obtain project name - # this often. Negative value disables periodic polling. In this mode project name is retrieved - # only when the current configuration, account or project id changes. - typeset -g POWERLEVEL9K_GCLOUD_REFRESH_PROJECT_NAME_SECONDS=60 - - # Custom icon. - # typeset -g POWERLEVEL9K_GCLOUD_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #[ google_app_cred: google application credentials (https://cloud.google.com/docs/authentication/production) ]# - # Show google_app_cred only when the command you are typing invokes one of these tools. - # Tip: Remove the next line to always show google_app_cred. - typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_SHOW_ON_COMMAND='terraform|pulumi|terragrunt' - - # Google application credentials classes for the purpose of using different colors, icons and - # expansions with different credentials. - # - # POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES is an array with even number of elements. The first - # element in each pair defines a pattern against which the current kubernetes context gets - # matched. More specifically, it's P9K_CONTENT prior to the application of context expansion - # (see below) that gets matched. If you unset all POWERLEVEL9K_GOOGLE_APP_CRED_*CONTENT_EXPANSION - # parameters, you'll see this value in your prompt. The second element of each pair in - # POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES defines the context class. Patterns are tried in order. - # The first match wins. - # - # For example, given these settings: - # - # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=( - # '*:*prod*:*' PROD - # '*:*test*:*' TEST - # '*' DEFAULT) - # - # If your current Google application credentials is "service_account deathray-testing x@y.com", - # its class is TEST because it doesn't match the pattern '* *prod* *' but does match '* *test* *'. - # - # You can define different colors, icons and content expansions for different classes: - # - # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_FOREGROUND=28 - # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_VISUAL_IDENTIFIER_EXPANSION='⭐' - # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_TEST_CONTENT_EXPANSION='$P9K_GOOGLE_APP_CRED_PROJECT_ID' - typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_CLASSES=( - # '*:*prod*:*' PROD # These values are examples that are unlikely - # '*:*test*:*' TEST # to match your needs. Customize them as needed. - '*' DEFAULT) - typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_FOREGROUND=7 - typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_BACKGROUND=4 - # typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_VISUAL_IDENTIFIER_EXPANSION='⭐' - - # Use POWERLEVEL9K_GOOGLE_APP_CRED_CONTENT_EXPANSION to specify the content displayed by - # google_app_cred segment. Parameter expansions are very flexible and fast, too. See reference: - # http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion. - # - # You can use the following parameters in the expansion. Each of them corresponds to one of the - # fields in the JSON file pointed to by GOOGLE_APPLICATION_CREDENTIALS. - # - # Parameter | JSON key file field - # ---------------------------------+--------------- - # P9K_GOOGLE_APP_CRED_TYPE | type - # P9K_GOOGLE_APP_CRED_PROJECT_ID | project_id - # P9K_GOOGLE_APP_CRED_CLIENT_EMAIL | client_email - # - # Note: ${VARIABLE//\%/%%} expands to ${VARIABLE} with all occurrences of '%' replaced by '%%'. - typeset -g POWERLEVEL9K_GOOGLE_APP_CRED_DEFAULT_CONTENT_EXPANSION='${P9K_GOOGLE_APP_CRED_PROJECT_ID//\%/%%}' - - ##############[ toolbox: toolbox name (https://github.com/containers/toolbox) ]############### - # Toolbox color. - typeset -g POWERLEVEL9K_TOOLBOX_FOREGROUND=0 - typeset -g POWERLEVEL9K_TOOLBOX_BACKGROUND=3 - # Don't display the name of the toolbox if it matches fedora-toolbox-*. - typeset -g POWERLEVEL9K_TOOLBOX_CONTENT_EXPANSION='${P9K_TOOLBOX_NAME:#fedora-toolbox-*}' - # Custom icon. - # typeset -g POWERLEVEL9K_TOOLBOX_VISUAL_IDENTIFIER_EXPANSION='⭐' - # Custom prefix. - # typeset -g POWERLEVEL9K_TOOLBOX_PREFIX='in ' - - ###############################[ public_ip: public IP address ]############################### - # Public IP color. - typeset -g POWERLEVEL9K_PUBLIC_IP_FOREGROUND=7 - typeset -g POWERLEVEL9K_PUBLIC_IP_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_PUBLIC_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ########################[ vpn_ip: virtual private network indicator ]######################### - # VPN IP color. - typeset -g POWERLEVEL9K_VPN_IP_FOREGROUND=0 - typeset -g POWERLEVEL9K_VPN_IP_BACKGROUND=6 - # When on VPN, show just an icon without the IP address. - # Tip: To display the private IP address when on VPN, remove the next line. - typeset -g POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION= - # Regular expression for the VPN network interface. Run `ifconfig` or `ip -4 a show` while on VPN - # to see the name of the interface. - typeset -g POWERLEVEL9K_VPN_IP_INTERFACE='(gpd|wg|(.*tun)|tailscale)[0-9]*|(zt.*)' - # If set to true, show one segment per matching network interface. If set to false, show only - # one segment corresponding to the first matching network interface. - # Tip: If you set it to true, you'll probably want to unset POWERLEVEL9K_VPN_IP_CONTENT_EXPANSION. - typeset -g POWERLEVEL9K_VPN_IP_SHOW_ALL=false - # Custom icon. - # typeset -g POWERLEVEL9K_VPN_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ###########[ ip: ip address and bandwidth usage for a specified network interface ]########### - # IP color. - typeset -g POWERLEVEL9K_IP_BACKGROUND=4 - typeset -g POWERLEVEL9K_IP_FOREGROUND=0 - # The following parameters are accessible within the expansion: - # - # Parameter | Meaning - # ----------------------+------------------------------------------- - # P9K_IP_IP | IP address - # P9K_IP_INTERFACE | network interface - # P9K_IP_RX_BYTES | total number of bytes received - # P9K_IP_TX_BYTES | total number of bytes sent - # P9K_IP_RX_BYTES_DELTA | number of bytes received since last prompt - # P9K_IP_TX_BYTES_DELTA | number of bytes sent since last prompt - # P9K_IP_RX_RATE | receive rate (since last prompt) - # P9K_IP_TX_RATE | send rate (since last prompt) - typeset -g POWERLEVEL9K_IP_CONTENT_EXPANSION='${P9K_IP_RX_RATE:+⇣$P9K_IP_RX_RATE }${P9K_IP_TX_RATE:+⇡$P9K_IP_TX_RATE }$P9K_IP_IP' - # Show information for the first network interface whose name matches this regular expression. - # Run `ifconfig` or `ip -4 a show` to see the names of all network interfaces. - typeset -g POWERLEVEL9K_IP_INTERFACE='[ew].*' - # Custom icon. - # typeset -g POWERLEVEL9K_IP_VISUAL_IDENTIFIER_EXPANSION='⭐' - - #########################[ proxy: system-wide http/https/ftp proxy ]########################## - # Proxy color. - typeset -g POWERLEVEL9K_PROXY_FOREGROUND=4 - typeset -g POWERLEVEL9K_PROXY_BACKGROUND=0 - # Custom icon. - # typeset -g POWERLEVEL9K_PROXY_VISUAL_IDENTIFIER_EXPANSION='⭐' - - ################################[ battery: internal battery ]################################# - # Show battery in red when it's below this level and not connected to power supply. - typeset -g POWERLEVEL9K_BATTERY_LOW_THRESHOLD=20 - typeset -g POWERLEVEL9K_BATTERY_LOW_FOREGROUND=1 - # Show battery in green when it's charging or fully charged. - typeset -g POWERLEVEL9K_BATTERY_{CHARGING,CHARGED}_FOREGROUND=2 - # Show battery in yellow when it's discharging. - typeset -g POWERLEVEL9K_BATTERY_DISCONNECTED_FOREGROUND=3 - # Battery pictograms going from low to high level of charge. - typeset -g POWERLEVEL9K_BATTERY_STAGES='\uf58d\uf579\uf57a\uf57b\uf57c\uf57d\uf57e\uf57f\uf580\uf581\uf578' - # Don't show the remaining time to charge/discharge. - typeset -g POWERLEVEL9K_BATTERY_VERBOSE=false - typeset -g POWERLEVEL9K_BATTERY_BACKGROUND=0 - - #####################################[ wifi: wifi speed ]##################################### - # WiFi color. - typeset -g POWERLEVEL9K_WIFI_FOREGROUND=0 - typeset -g POWERLEVEL9K_WIFI_BACKGROUND=4 - # Custom icon. - # typeset -g POWERLEVEL9K_WIFI_VISUAL_IDENTIFIER_EXPANSION='⭐' - - # Use different colors and icons depending on signal strength ($P9K_WIFI_BARS). - # - # # Wifi colors and icons for different signal strength levels (low to high). - # typeset -g my_wifi_fg=(0 0 0 0 0) # <-- change these values - # typeset -g my_wifi_icon=('WiFi' 'WiFi' 'WiFi' 'WiFi' 'WiFi') # <-- change these values - # - # typeset -g POWERLEVEL9K_WIFI_CONTENT_EXPANSION='%F{${my_wifi_fg[P9K_WIFI_BARS+1]}}$P9K_WIFI_LAST_TX_RATE Mbps' - # typeset -g POWERLEVEL9K_WIFI_VISUAL_IDENTIFIER_EXPANSION='%F{${my_wifi_fg[P9K_WIFI_BARS+1]}}${my_wifi_icon[P9K_WIFI_BARS+1]}' - # - # The following parameters are accessible within the expansions: - # - # Parameter | Meaning - # ----------------------+--------------- - # P9K_WIFI_SSID | service set identifier, a.k.a. network name - # P9K_WIFI_LINK_AUTH | authentication protocol such as "wpa2-psk" or "none"; empty if unknown - # P9K_WIFI_LAST_TX_RATE | wireless transmit rate in megabits per second - # P9K_WIFI_RSSI | signal strength in dBm, from -120 to 0 - # P9K_WIFI_NOISE | noise in dBm, from -120 to 0 - # P9K_WIFI_BARS | signal strength in bars, from 0 to 4 (derived from P9K_WIFI_RSSI and P9K_WIFI_NOISE) - - ####################################[ time: current time ]#################################### - # Current time color. - typeset -g POWERLEVEL9K_TIME_FOREGROUND=0 - typeset -g POWERLEVEL9K_TIME_BACKGROUND=7 - # Format for the current time: 09:51:02. See `man 3 strftime`. - typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}' - # If set to true, time will update when you hit enter. This way prompts for the past - # commands will contain the start times of their commands as opposed to the default - # behavior where they contain the end times of their preceding commands. - typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false - # Custom icon. - # typeset -g POWERLEVEL9K_TIME_VISUAL_IDENTIFIER_EXPANSION='⭐' - # Custom prefix. - # typeset -g POWERLEVEL9K_TIME_PREFIX='at ' - - # Example of a user-defined prompt segment. Function prompt_example will be called on every - # prompt if `example` prompt segment is added to POWERLEVEL9K_LEFT_PROMPT_ELEMENTS or - # POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS. It displays an icon and yellow text on red background - # greeting the user. - # - # Type `p10k help segment` for documentation and a more sophisticated example. - function prompt_example() { - p10k segment -b 1 -f 3 -i '⭐' -t 'hello, %n' - } - - # User-defined prompt segments may optionally provide an instant_prompt_* function. Its job - # is to generate the prompt segment for display in instant prompt. See - # https://github.com/romkatv/powerlevel10k#instant-prompt. - # - # Powerlevel10k will call instant_prompt_* at the same time as the regular prompt_* function - # and will record all `p10k segment` calls it makes. When displaying instant prompt, Powerlevel10k - # will replay these calls without actually calling instant_prompt_*. It is imperative that - # instant_prompt_* always makes the same `p10k segment` calls regardless of environment. If this - # rule is not observed, the content of instant prompt will be incorrect. - # - # Usually, you should either not define instant_prompt_* or simply call prompt_* from it. If - # instant_prompt_* is not defined for a segment, the segment won't be shown in instant prompt. - function instant_prompt_example() { - # Since prompt_example always makes the same `p10k segment` calls, we can call it from - # instant_prompt_example. This will give us the same `example` prompt segment in the instant - # and regular prompts. - prompt_example - } - - # User-defined prompt segments can be customized the same way as built-in segments. - typeset -g POWERLEVEL9K_EXAMPLE_FOREGROUND=3 - typeset -g POWERLEVEL9K_EXAMPLE_BACKGROUND=1 - # typeset -g POWERLEVEL9K_EXAMPLE_VISUAL_IDENTIFIER_EXPANSION='⭐' - - # Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt - # when accepting a command line. Supported values: - # - # - off: Don't change prompt when accepting a command line. - # - always: Trim down prompt when accepting a command line. - # - same-dir: Trim down prompt when accepting a command line unless this is the first command - # typed after changing current working directory. - typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off - - # Instant prompt mode. - # - # - off: Disable instant prompt. Choose this if you've tried instant prompt and found - # it incompatible with your zsh configuration files. - # - quiet: Enable instant prompt and don't print warnings when detecting console output - # during zsh initialization. Choose this if you've read and understood - # https://github.com/romkatv/powerlevel10k#instant-prompt. - # - verbose: Enable instant prompt and print a warning when detecting console output during - # zsh initialization. Choose this if you've never tried instant prompt, haven't - # seen the warning, or if you are unsure what this all means. - typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet - - # Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized. - # For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload - # can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you - # really need it. - typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true - - # If p10k is already loaded, reload configuration. - # This works even with POWERLEVEL9K_DISABLE_HOT_RELOAD=true. - (( ! $+functions[p10k] )) || p10k reload -} - -# Tell `p10k configure` which file it should overwrite. -typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a} - -(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]} -'builtin' 'unset' 'p10k_config_opts' diff --git a/gui/gnome/autocustom-gnome-macos/conf/.zshrc b/gui/gnome/autocustom-gnome-macos/conf/.zshrc deleted file mode 100644 index 81b2c6ab..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/.zshrc +++ /dev/null @@ -1,112 +0,0 @@ -# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. -# Initialization code that may require console input (password prompts, [y/n] -# confirmations, etc.) must go above this block; everything else may go below. -if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then - source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" -fi - -# If you come from bash you might have to change your $PATH. -# export PATH=$HOME/bin:$HOME/.local/bin:/usr/local/bin:$PATH - -# Path to your oh-my-zsh installation. -export ZSH="$HOME/.oh-my-zsh" - -# Set name of the theme to load --- if set to "random", it will -# load a random theme each time oh-my-zsh is loaded, in which case, -# to know which specific one was loaded, run: echo $RANDOM_THEME -# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes -# ZSH_THEME="robbyrussell" -ZSH_THEME="powerlevel10k/powerlevel10k" - -# Set list of themes to pick from when loading at random -# Setting this variable when ZSH_THEME=random will cause zsh to load -# a theme from this variable instead of looking in $ZSH/themes/ -# If set to an empty array, this variable will have no effect. -# ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) - -# Uncomment the following line to use case-sensitive completion. -# CASE_SENSITIVE="true" - -# Uncomment the following line to use hyphen-insensitive completion. -# Case-sensitive completion must be off. _ and - will be interchangeable. -# HYPHEN_INSENSITIVE="true" - -# Uncomment one of the following lines to change the auto-update behavior -# zstyle ':omz:update' mode disabled # disable automatic updates -# zstyle ':omz:update' mode auto # update automatically without asking -# zstyle ':omz:update' mode reminder # just remind me to update when it's time - -# Uncomment the following line to change how often to auto-update (in days). -# zstyle ':omz:update' frequency 13 - -# Uncomment the following line if pasting URLs and other text is messed up. -# DISABLE_MAGIC_FUNCTIONS="true" - -# Uncomment the following line to disable colors in ls. -# DISABLE_LS_COLORS="true" - -# Uncomment the following line to disable auto-setting terminal title. -# DISABLE_AUTO_TITLE="true" - -# Uncomment the following line to enable command auto-correction. -# ENABLE_CORRECTION="true" - -# Uncomment the following line to display red dots whilst waiting for completion. -# You can also set it to another string to have that shown instead of the default red dots. -# e.g. COMPLETION_WAITING_DOTS="%F{yellow}waiting...%f" -# Caution: this setting can cause issues with multiline prompts in zsh < 5.7.1 (see #5765) -# COMPLETION_WAITING_DOTS="true" - -# Uncomment the following line if you want to disable marking untracked files -# under VCS as dirty. This makes repository status check for large repositories -# much, much faster. -# DISABLE_UNTRACKED_FILES_DIRTY="true" - -# Uncomment the following line if you want to change the command execution time -# stamp shown in the history command output. -# You can set one of the optional three formats: -# "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" -# or set a custom format using the strftime function format specifications, -# see 'man strftime' for details. -# HIST_STAMPS="mm/dd/yyyy" - -# Would you like to use another custom folder than $ZSH/custom? -# ZSH_CUSTOM=/path/to/new-custom-folder - -# Which plugins would you like to load? -# Standard plugins can be found in $ZSH/plugins/ -# Custom plugins may be added to $ZSH_CUSTOM/plugins/ -# Example format: plugins=(rails git textmate ruby lighthouse) -# Add wisely, as too many plugins slow down shell startup. -plugins=(git) - -source $ZSH/oh-my-zsh.sh - -# User configuration - -# export MANPATH="/usr/local/man:$MANPATH" - -# You may need to manually set your language environment -# export LANG=en_US.UTF-8 - -# Preferred editor for local and remote sessions -# if [[ -n $SSH_CONNECTION ]]; then -# export EDITOR='vim' -# else -# export EDITOR='mvim' -# fi - -# Compilation flags -# export ARCHFLAGS="-arch x86_64" - -# Set personal aliases, overriding those provided by oh-my-zsh libs, -# plugins, and themes. Aliases can be placed here, though oh-my-zsh -# users are encouraged to define aliases within the ZSH_CUSTOM folder. -# For a full list of active aliases, run `alias`. -# -# Example aliases -# alias zshconfig="mate ~/.zshrc" -# alias ohmyzsh="mate ~/.oh-my-zsh" - -# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh. -[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh diff --git a/gui/gnome/autocustom-gnome-macos/conf/cava/config b/gui/gnome/autocustom-gnome-macos/conf/cava/config deleted file mode 100644 index 60ddcd11..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/cava/config +++ /dev/null @@ -1,12 +0,0 @@ -[color] - -gradient = 1 - -gradient_color_1 = '#80DEEA' # Material Cyan -gradient_color_2 = '#81D4FA' # Material Light Blue -gradient_color_3 = '#4FC3F7' # Material Blue -gradient_color_4 = '#42A5F5' # Material Blue Accent -gradient_color_5 = '#7E57C2' # Material Deep Purple -gradient_color_6 = '#BA68C8' # Material Purple -gradient_color_7 = '#EC407A' # Material Pink -gradient_color_8 = '#E57373' # Material Red diff --git a/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/bar_spectrum.frag b/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/bar_spectrum.frag deleted file mode 100644 index b0789132..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/bar_spectrum.frag +++ /dev/null @@ -1,79 +0,0 @@ -#version 330 - -in vec2 fragCoord; -out vec4 fragColor; - -// bar values. defaults to left channels first (low to high), then right (high to low). -uniform float bars[512]; - -uniform int bars_count; // number of bars (left + right) (configurable) -uniform int bar_width; // bar width (configurable), not used here -uniform int bar_spacing; // space bewteen bars (configurable) - -uniform vec3 u_resolution; // window resolution - -//colors, configurable in cava config file (r,g,b) (0.0 - 1.0) -uniform vec3 bg_color; // background color -uniform vec3 fg_color; // foreground color - -uniform int gradient_count; -uniform vec3 gradient_colors[8]; // gradient colors - -vec3 normalize_C(float y,vec3 col_1, vec3 col_2, float y_min, float y_max) -{ - //create color based on fraction of this color and next color - float yr = (y - y_min) / (y_max - y_min); - return col_1 * (1.0 - yr) + col_2 * yr; -} - -void main() -{ - // find which bar to use based on where we are on the x axis - float x = u_resolution.x * fragCoord.x; - int bar = int(bars_count * fragCoord.x); - - //calculate a bar size - float bar_size = u_resolution.x / bars_count; - - //the y coordinate and bar values are the same - float y = bars[bar]; - - // make sure there is a thin line at bottom - if (y * u_resolution.y < 1.0) - { - y = 1.0 / u_resolution.y; - } - - //draw the bar up to current height - if (y > fragCoord.y) - { - //make some space between bars basen on settings - if (x > (bar + 1) * (bar_size) - bar_spacing) - { - fragColor = vec4(bg_color,1.0); - } - else - { - if (gradient_count == 0) - { - fragColor = vec4(fg_color,1.0); - } - else - { - //find which color in the configured gradient we are at - int color = int((gradient_count - 1) * fragCoord.y); - - //find where on y this and next color is supposed to be - float y_min = color / (gradient_count - 1.0); - float y_max = (color + 1.0) / (gradient_count - 1.0); - - //make color - fragColor = vec4(normalize_C(fragCoord.y, gradient_colors[color], gradient_colors[color + 1], y_min, y_max), 1.0); - } - } - } - else - { - fragColor = vec4(bg_color,1.0); - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/northern_lights.frag b/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/northern_lights.frag deleted file mode 100644 index ecd859a7..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/northern_lights.frag +++ /dev/null @@ -1,34 +0,0 @@ -#version 330 - -in vec2 fragCoord; -out vec4 fragColor; - -// bar values. defaults to left channels first (low to high), then right (high to low). -uniform float bars[512]; - -uniform int bars_count; // number of bars (left + right) (configurable) - -uniform vec3 u_resolution; // window resolution, not used here - -//colors, configurable in cava config file -uniform vec3 bg_color; // background color(r,g,b) (0.0 - 1.0), not used here -uniform vec3 fg_color; // foreground color, not used here - -void main() -{ - // find which bar to use based on where we are on the x axis - int bar = int(bars_count * fragCoord.x); - - float bar_y = 1.0 - abs((fragCoord.y - 0.5)) * 2.0; - float y = (bars[bar]) * bar_y; - - float bar_x = (fragCoord.x - float(bar) / float(bars_count)) * bars_count; - float bar_r = 1.0 - abs((bar_x - 0.5)) * 2; - - bar_r = bar_r * bar_r * 2; - - // set color - fragColor.r = fg_color.x * y * bar_r; - fragColor.g = fg_color.y * y * bar_r; - fragColor.b = fg_color.z * y * bar_r; -} diff --git a/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/pass_through.vert b/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/pass_through.vert deleted file mode 100644 index a4f20e52..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/cava/shaders/pass_through.vert +++ /dev/null @@ -1,14 +0,0 @@ -#version 330 - - -// Input vertex data, different for all executions of this shader. -layout(location = 0) in vec3 vertexPosition_modelspace; - -// Output data ; will be interpolated for each fragment. -out vec2 fragCoord; - -void main() -{ - gl_Position = vec4(vertexPosition_modelspace,1); - fragCoord = (vertexPosition_modelspace.xy+vec2(1,1))/2.0; -} diff --git a/gui/gnome/autocustom-gnome-macos/conf/gnome46-macos-fedora40.conf b/gui/gnome/autocustom-gnome-macos/conf/gnome46-macos-fedora40.conf deleted file mode 100644 index e9a2f701..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/gnome46-macos-fedora40.conf +++ /dev/null @@ -1,495 +0,0 @@ -[ca/desrt/dconf-editor] -saved-pathbar-path='/' -saved-view='/' -show-warning=false -window-height=500 -window-is-maximized=false -window-width=540 - -[com/mattjakeman/ExtensionManager] -is-maximized=false -last-used-version='0.5.0' - -[org/gnome/Console] -custom-font='FiraCode Nerd Font Mono 10' -last-window-maximised=false -last-window-size=(857, 511) -use-system-font=false - -[org/gnome/Music] -window-maximized=false -window-size=[767, 668] - -[org/gnome/Weather] -locations=[<(uint32 2, <('New York City, Central Park', 'KNYC', false, [(0.71180344078725644, -1.2909618758762367)], @a(dd) [])>)>] -window-height=497 -window-maximized=false -window-width=707 - -[org/gnome/calculator] -accuracy=9 -angle-units='degrees' -base=10 -button-mode='basic' -number-format='automatic' -show-thousands=false -show-zeroes=false -source-currency='' -source-units='degree' -target-currency='' -target-units='radian' -window-maximized=false -window-size=(360, 506) -word-size=64 - -[org/gnome/calendar] -active-view='week' -window-maximized=false -window-size=(986, 600) - -[org/gnome/clocks/state/window] -maximized=false -panel-id='world' -size=(870, 690) - -[org/gnome/control-center] -last-panel='system' -window-state=(980, 640, true) - -[org/gnome/desktop/app-folders] -folder-children=['Utilities', 'YaST', 'Pardus'] - -[org/gnome/desktop/app-folders/folders/Pardus] -categories=['X-Pardus-Apps'] -name='X-Pardus-Apps.directory' -translate=true - -[org/gnome/desktop/app-folders/folders/Utilities] -apps=['org.gnome.baobab.desktop', 'org.gnome.DiskUtility.desktop', 'org.gnome.seahorse.Application.desktop', 'org.gnome.Logs.desktop', 'avahi-discover.desktop'] -categories=['X-GNOME-Utilities'] -excluded-apps=['org.gnome.Console.desktop', 'org.gnome.Evince.desktop', 'org.gnome.Characters.desktop', 'nm-connection-editor.desktop', 'org.gnome.font-viewer.desktop'] -name='X-GNOME-Utilities.directory' -translate=true - -[org/gnome/desktop/app-folders/folders/YaST] -categories=['X-SuSE-YaST'] -name='suse-yast.directory' -translate=true - -[org/gnome/desktop/background] -color-shading-type='solid' -picture-options='zoom' -picture-uri='file:///usr/share/backgrounds/macosw/MacVentura-Light.jpg' -picture-uri-dark='file:///usr/share/backgrounds/macosw/MacVentura-Dark.jpg' -primary-color='#000000000000' -secondary-color='#000000000000' - -[org/gnome/desktop/input-sources] -sources=[('xkb', 'us')] -xkb-options=@as [] - -[org/gnome/desktop/interface] -color-scheme='default' -cursor-theme='WhiteSur-cursors' -document-font-name='SF Pro Display 10' -enable-animations=true -font-hinting='full' -font-name='SF Pro Display 10' -gtk-theme='WhiteSur-Light' -icon-theme='WhiteSur-light' -monospace-font-name='MesloLGS NF 13' -toolkit-accessibility=false - -[org/gnome/desktop/notifications] -application-children=['gnome-power-panel', 'org-gnome-calendar', 'firefox', 'com-mattjakeman-extensionmanager', 'org-gnome-settings'] - -[org/gnome/desktop/notifications/application/com-mattjakeman-extensionmanager] -application-id='com.mattjakeman.ExtensionManager.desktop' - -[org/gnome/desktop/notifications/application/firefox] -application-id='firefox.desktop' - -[org/gnome/desktop/notifications/application/gnome-power-panel] -application-id='gnome-power-panel.desktop' - -[org/gnome/desktop/notifications/application/org-gnome-calendar] -application-id='org.gnome.Calendar.desktop' - -[org/gnome/desktop/notifications/application/org-gnome-settings] -application-id='org.gnome.Settings.desktop' - -[org/gnome/desktop/peripherals/keyboard] -numlock-state=true - -[org/gnome/desktop/peripherals/touchpad] -two-finger-scrolling-enabled=true - -[org/gnome/desktop/privacy] -old-files-age=uint32 30 -recent-files-max-age=-1 - -[org/gnome/desktop/screensaver] -color-shading-type='solid' -picture-options='zoom' -picture-uri='file:///usr/share/backgrounds/macosw/MacVentura-Light.jpg' -primary-color='#000000000000' -secondary-color='#000000000000' - -[org/gnome/desktop/search-providers] -disabled=['org.gnome.Characters.desktop', 'org.gnome.seahorse.Application.desktop'] -sort-order=['org.gnome.Contacts.desktop', 'org.gnome.Documents.desktop', 'org.gnome.Nautilus.desktop'] - -[org/gnome/desktop/session] -idle-delay=uint32 300 - -[org/gnome/desktop/wm/preferences] -button-layout='close,maximize,minimize:' - -[org/gnome/evolution-data-server] -migrated=true - -[org/gnome/file-roller/listing] -list-mode='as-folder' -name-column-width=184 -show-path=false -sort-method='name' -sort-type='ascending' - -[org/gnome/file-roller/ui] -sidebar-width=200 -window-height=480 -window-width=600 - -[org/gnome/gnome-system-monitor] -show-dependencies=false -show-whose-processes='user' - -[org/gnome/gnome-system-monitor/disktreenew] -col-6-visible=true -col-6-width=0 -columns-order=[5] -sort-col=1 -sort-order=0 - -[org/gnome/maps] -last-viewed-location=[0.0, 0.0] -map-type='MapsStreetSource' -transportation-type='pedestrian' -window-maximized=false -window-size=[682, 493] -zoom-level=2 - -[org/gnome/mutter] -center-new-windows=true -overlay-key='Super_L' - -[org/gnome/mutter/keybindings] -toggle-tiled-left=@as [] -toggle-tiled-right=@as [] - -[org/gnome/nautilus/icon-view] -default-zoom-level='medium' - -[org/gnome/nautilus/preferences] -default-folder-viewer='icon-view' -migrated-gtk-settings=true -search-filter-time-type='last_modified' - -[org/gnome/nautilus/window-state] -initial-size=(770, 513) -maximized=false - -[org/gnome/nm-applet/eap/b2694852-f55e-3421-a3a8-3c368465ecb2] -ignore-ca-cert=false -ignore-phase2-ca-cert=false - -[org/gnome/pomodoro/state] -timer-date='2024-05-24T01:55:24+0000' -timer-elapsed=0.0 -timer-paused=false -timer-score=0.0 -timer-state='null' -timer-state-date='2024-05-24T01:55:24+0000' -timer-state-duration=0.0 - -[org/gnome/portal/filechooser/gnome-background-panel] -last-folder-path='/usr/share/backgrounds/macosw' - -[org/gnome/settings-daemon/plugins/power] -sleep-inactive-ac-timeout=3600 -sleep-inactive-ac-type='nothing' - -[org/gnome/shell] -app-picker-layout=[{'display-im6.q16.desktop': <{'position': <0>}>, 'nm-connection-editor.desktop': <{'position': <1>}>, 'org.gnome.tweaks.desktop': <{'position': <2>}>, 'gnome-language-selector.desktop': <{'position': <3>}>, 'org.gnome.SystemMonitor.desktop': <{'position': <4>}>, 'org.gnome.clocks.desktop': <{'position': <5>}>, 'update-manager.desktop': <{'position': <6>}>, 'gnome-session-properties.desktop': <{'position': <7>}>, 'org.gnome.font-viewer.desktop': <{'position': <8>}>, 'software-properties-drivers.desktop': <{'position': <9>}>, 'org.gnome.Evince.desktop': <{'position': <10>}>, 'org.gnome.Characters.desktop': <{'position': <11>}>, 'software-properties-gtk.desktop': <{'position': <12>}>, 'org.gnome.Contacts.desktop': <{'position': <13>}>}, {'Utilities': <{'position': <0>}>, 'org.gnome.PowerStats.desktop': <{'position': <1>}>, 'yelp.desktop': <{'position': <2>}>, 'ca.desrt.dconf-editor.desktop': <{'position': <3>}>, 'org.gnome.Console.desktop': <{'position': <4>}>, 'com.mattjakeman.ExtensionManager.desktop': <{'position': <5>}>, 'snap-store_snap-store.desktop': <{'position': <6>}>, 'org.gnome.Connections.desktop': <{'position': <7>}>, 'firefox_firefox.desktop': <{'position': <8>}>, 'firmware-updater_firmware-updater.desktop': <{'position': <9>}>, 'org.gnome.Pomodoro.desktop': <{'position': <10>}>}] -disable-user-extensions=false -disabled-extensions=['ding@rastersoft.com', 'ubuntu-dock@ubuntu.com', 'tiling-assistant@ubuntu.com', 'azclock@azclock.gitlab.com', 'quick-settings-tweaks@qwreey', 'quick-settings-avatar@d-go', 'arcmenu@arcmenu.com', 'dash2dock-lite@icedman.github.com', 'openbar@neuromorph', 'compact-quick-settings@gnome-shell-extensions.mariospr.org', 'apps-menu@gnome-shell-extensions.gcampax.github.com', 'ubuntu-appindicators@ubuntu.com'] -enabled-extensions=['SettingsCenter@lauinger-clan.de', 'windowgestures@extension.amarullz.com', 'appindicatorsupport@rgcjonas.gmail.com', 'compiz-alike-magic-lamp-effect@hermes83.github.com', 'CoverflowAltTab@palatis.blogspot.com', 'dash-to-dock@micxgx.gmail.com', 'date-menu-formatter@marcinjakubowski.github.com', 'desktop-cube@schneegans.github.com', 'gsconnect@andyholmes.github.io', 'logomenu@aryan_k', 'media-progress@krypion17', 'order-extensions@wa4557.github.com', 'nightthemeswitcher@romainvigier.fr', 'moveclock@kuvaus.org', 'places-menu@gnome-shell-extensions.gcampax.github.com', 'power-profile-indicator@laux.wtf', 'search-light@icedman.github.com', 'user-theme@gnome-shell-extensions.gcampax.github.com', 'just-perfection-desktop@just-perfection', 'blur-my-shell@aunetx', 'appmenu-is-back@fthx', 'pomodoro@arun.codito.in'] -favorite-apps=['org.gnome.Nautilus.desktop', 'org.gnome.Maps.desktop', 'org.gnome.Software.desktop', 'org.gnome.Weather.desktop', 'org.gnome.eog.desktop', 'org.gnome.TextEditor.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.gedit.desktop', 'org.gnome.Calculator.desktop', 'org.gnome.Settings.desktop'] -last-selected-power-profile='power-saver' -welcome-dialog-last-shown-version='46.0' - -[org/gnome/shell/extensions/Logo-menu] -hide-icon-shadow=false -menu-button-extensions-app='com.mattjakeman.ExtensionManager.desktop' -menu-button-icon-image=0 -menu-button-icon-size=20 -show-activities-button=true -show-lockscreen=true -show-power-options=true -symbolic-icon=true -use-custom-icon=false - -[org/gnome/shell/extensions/blur-my-shell] -pipelines={'pipeline_default': {'name': <'Default'>, 'effects': <[<{'type': <'native_static_gaussian_blur'>, 'id': <'effect_000000000000'>, 'params': <{'radius': <30>, 'brightness': <0.59999999999999998>}>}>]>}, 'pipeline_default_rounded': {'name': <'Default rounded'>, 'effects': <[<{'type': <'native_static_gaussian_blur'>, 'id': <'effect_000000000001'>, 'params': <{'radius': <30>, 'brightness': <0.59999999999999998>}>}>, <{'type': <'corner'>, 'id': <'effect_000000000002'>, 'params': <{'radius': <30>, 'corners_top': , 'corners_bottom': }>}>]>}} -settings-version=2 - -[org/gnome/shell/extensions/blur-my-shell/appfolder] -blur=true -brightness=0.59999999999999998 -sigma=30 - -[org/gnome/shell/extensions/blur-my-shell/applications] -blur=true -whitelist=['org.gnome.Nautilus', 'org.gnome.Console', 'org.gnome.Calculator'] - -[org/gnome/shell/extensions/blur-my-shell/dash-to-dock] -blur=true -brightness=0.59999999999999998 -override-background=true -pipeline='pipeline_default_rounded' -sigma=30 -static-blur=true -style-dash-to-dock=0 -unblur-in-overview=false - -[org/gnome/shell/extensions/blur-my-shell/dash-to-panel] -blur-original-panel=true - -[org/gnome/shell/extensions/blur-my-shell/lockscreen] -pipeline='pipeline_default' - -[org/gnome/shell/extensions/blur-my-shell/overview] -blur=true -pipeline='pipeline_default' -style-components=0 - -[org/gnome/shell/extensions/blur-my-shell/panel] -brightness=0.59999999999999998 -force-light-text=true -override-background=true -override-background-dynamically=false -pipeline='pipeline_default' -sigma=30 -static-blur=true -style-panel=0 - -[org/gnome/shell/extensions/blur-my-shell/screenshot] -pipeline='pipeline_default' - -[org/gnome/shell/extensions/blur-my-shell/window-list] -brightness=0.59999999999999998 -sigma=30 - -[org/gnome/shell/extensions/coverflowalttab] -animation-time=0.5 -blur-radius=0 -current-workspace-only='all' -enforce-primary-monitor=true -hide-panel=true -highlight-mouse-over=false -icon-has-shadow=false -icon-style='Classic' -invert-swipes=true -overlay-icon-opacity=0.75 -perspective-correction-method='Adjust Angles' -preview-to-monitor-ratio=0.52300000000000002 -randomize-animation-times=false -switch-application-behaves-like-switch-windows=false -switch-per-monitor=true -switcher-background-color=(0.031372549019607843, 0.37647058823529411, 0.94901960784313721) -switcher-looping-method='Carousel' -switcher-style='Coverflow' -use-glitch-effect=false -use-tint=false - -[org/gnome/shell/extensions/dash-to-dock] -always-center-icons=false -apply-custom-theme=true -autohide=true -autohide-in-fullscreen=true -background-color='rgb(255,255,255)' -background-opacity=0.80000000000000004 -click-action='focus-minimize-or-previews' -custom-background-color=false -custom-theme-shrink=true -dash-max-icon-size=48 -disable-overview-on-startup=true -dock-fixed=false -dock-position='BOTTOM' -extend-height=false -height-fraction=0.90000000000000002 -icon-size-fixed=true -intellihide=true -intellihide-mode='MAXIMIZED_WINDOWS' -middle-click-action='launch' -preferred-monitor=-2 -preferred-monitor-by-connector='Virtual-1' -preview-size-scale=0.29999999999999999 -running-indicator-style='DOTS' -shift-click-action='minimize' -shift-middle-click-action='launch' -show-apps-at-top=true -show-mounts-network=true -transparency-mode='DYNAMIC' - -[org/gnome/shell/extensions/date-menu-formatter] -apply-all-panels=true -formatter='01_luxon' -pattern='EEE, d, hh:mm a' -text-align='right' -use-default-calendar=true - -[org/gnome/shell/extensions/ding] -check-x11wayland=true - -[org/gnome/shell/extensions/gsconnect] -id='9f582610-566c-47c5-b768-9b7b0fd82196' -name='linuxscoop' - -[org/gnome/shell/extensions/just-perfection] -clock-menu-position=0 -clock-menu-position-offset=0 -controls-manager-spacing-size=0 -notification-banner-position=2 -osd-position=8 -panel-button-padding-size=11 -panel-indicator-padding-size=11 -search=true -startup-status=0 -theme=false -workspaces-in-app-grid=false - -[org/gnome/shell/extensions/moveclock] -clock-before-statusmenu=false - -[org/gnome/shell/extensions/ncom/github/hermes83/compiz-alike-magic-lamp-effect] -effect='default' - -[org/gnome/shell/extensions/nightthemeswitcher/commands] -enabled=true - -[org/gnome/shell/extensions/nightthemeswitcher/time] -manual-schedule=true -nightthemeswitcher-ondemand-keybinding=['t'] - -[org/gnome/shell/extensions/order-icons] -icons-blacklist=['ArcMenu'] -order-icons-center=@as [] -order-icons-left=['LogoMenu', 'activities', 'places-menu', 'appmenu-indicator'] -order-icons-right=['686fd560-1c6c-11ef-823f-55c5a292da21', 'd343a980-1c6b-11ef-a0d7-896d89a1cdfb', 'c863bc00-1bd8-11ef-b856-33645d49c08c', 'a8aca1b0-1bd3-11ef-9fe0-7143877a2ff4', 'gnome-pomodoro', 'livepatch', 'software-update-available', 'a11y', 'keyboard', 'dwellClick', 'screenSharing', 'screenRecording', 'quickSettings', 'dateMenu'] - -[org/gnome/shell/extensions/search-light] -blur-background=true -blur-brightness=0.59999999999999998 -blur-sigma=30.0 -border-radius=3.384297520661157 -border-thickness=0 -currency-converter=true -entry-font-size=1 -monitor-count=1 -popup-at-cursor-monitor=true -preferred-monitor=0 -scale-height=0.10000000000000001 -scale-width=0.0 -secondary-shortcut-search=['space'] -shortcut-search=['space'] -show-panel-icon=false -unit-converter=true - -[org/gnome/shell/extensions/user-theme] -name='WhiteSur-Light' - -[org/gnome/shell/extensions/windowgestures] -three-finger=true -ui-theme=0 - -[org/gnome/shell/weather] -automatic-location=true -locations=[<(uint32 2, <('New York City, Central Park', 'KNYC', false, [(0.71180344078725644, -1.2909618758762367)], @a(dd) [])>)>] - -[org/gnome/shell/world-clocks] -locations=@av [] - -[org/gnome/software] -check-timestamp=int64 1716508346 -flatpak-purge-timestamp=int64 1716096087 - -[org/gnome/terminal/legacy] -theme-variant='system' - -[org/gnome/terminal/legacy/profiles:] -default='7b4df471-ff52-4b7f-b8e7-0049c20e0a83' -list=['57fdd101-b1ed-4722-8584-7d69b977180b', '7b4df471-ff52-4b7f-b8e7-0049c20e0a83'] - -[org/gnome/terminal/legacy/profiles:/:57fdd101-b1ed-4722-8584-7d69b977180b] -allow-bold=true -background-color='#181816161616' -background-transparency-percent=7 -bold-color='#C5C5C9C9C5C5' -bold-color-same-as-fg=true -cursor-background-color='#C8C8C0C09393' -cursor-colors-set=true -cursor-foreground-color='#181816161616' -custom-command='/bin/zsh' -font='MesloLGS NF 10' -foreground-color='#C5C5C9C9C5C5' -login-shell=false -palette=['#0D0D0C0C0C0C', '#C4C474746E6E', '#8A8A9A9A7B7B', '#C4C4B2B28A8A', '#8B8BA4A4B0B0', '#A2A29292A3A3', '#8E8EA4A4A2A2', '#C8C8C0C09393', '#A6A6A6A69C9C', '#E4E468687676', '#8787A9A98787', '#E6E6C3C38484', '#7F7FB4B4CACA', '#93938A8AA9A9', '#7A7AA8A89F9F', '#C5C5C9C9C5C5'] -use-custom-command=true -use-system-font=false -use-theme-background=false -use-theme-colors=true -use-theme-transparency=false -use-transparent-background=true -visible-name='Kanagawa Dragon' - -[org/gnome/terminal/legacy/profiles:/:7b4df471-ff52-4b7f-b8e7-0049c20e0a83] -allow-bold=true -background-color='#1F1F1F1F2828' -background-transparency-percent=4 -bold-color='#DCDCD7D7BABA' -bold-color-same-as-fg=true -cursor-background-color='#DCDCD7D7BABA' -cursor-colors-set=true -cursor-foreground-color='#1F1F1F1F2828' -custom-command='/bin/zsh' -font='MesloLGS NF 10' -foreground-color='#DCDCD7D7BABA' -login-shell=false -palette=['#090906061818', '#C3C340404343', '#767694946A6A', '#C0C0A3A36E6E', '#7E7E9C9CD8D8', '#95957F7FB8B8', '#6A6A95958989', '#DCDCD7D7BABA', '#727271716969', '#E8E824242424', '#9898BBBB6C6C', '#E6E6C3C38484', '#7F7FB4B4CACA', '#93938A8AA9A9', '#7A7AA8A89F9F', '#C8C8C0C09393'] -use-custom-command=true -use-system-font=false -use-theme-background=false -use-theme-colors=false -use-theme-transparency=false -use-transparent-background=true -visible-name='Kanagawa' - -[org/gnome/terminal/legacy/profiles:/:cc6d05ce-8deb-4aec-b4b8-95c0b18e29d1] -allow-bold=true -use-theme-background=false - -[org/gtk/gtk4/settings/color-chooser] -selected-color=(true, 1.0, 1.0, 1.0, 1.0) - -[org/gtk/gtk4/settings/file-chooser] -date-format='regular' -location-mode='path-bar' -show-hidden=true -sidebar-width=140 -sort-column='name' -sort-directories-first=true -sort-order='ascending' -type-format='category' -view-type='list' -window-size=(801, 822) \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/conf/gnome46-macos-ubuntu2404.conf b/gui/gnome/autocustom-gnome-macos/conf/gnome46-macos-ubuntu2404.conf deleted file mode 100644 index 5565a43f..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/gnome46-macos-ubuntu2404.conf +++ /dev/null @@ -1,507 +0,0 @@ -[apps/update-manager] -launch-count=1 -launch-time=int64 1716009237 - -[ca/desrt/dconf-editor] -saved-pathbar-path='/' -saved-view='/' -show-warning=false -window-height=500 -window-is-maximized=false -window-width=540 - -[com/mattjakeman/ExtensionManager] -is-maximized=false -last-used-version='0.5.0' - -[com/ubuntu/update-notifier] -release-check-time=uint32 1715914293 - -[org/gnome/Console] -custom-font='FiraCode Nerd Font Mono 10' -last-window-maximised=false -last-window-size=(857, 511) -use-system-font=false - -[org/gnome/Music] -window-maximized=false -window-size=[767, 668] - -[org/gnome/Weather] -locations=[<(uint32 2, <('New York City, Central Park', 'KNYC', false, [(0.71180344078725644, -1.2909618758762367)], @a(dd) [])>)>] -window-height=497 -window-maximized=false -window-width=707 - -[org/gnome/calculator] -accuracy=9 -angle-units='degrees' -base=10 -button-mode='basic' -number-format='automatic' -show-thousands=false -show-zeroes=false -source-currency='' -source-units='degree' -target-currency='' -target-units='radian' -window-maximized=false -window-size=(360, 506) -word-size=64 - -[org/gnome/calendar] -active-view='week' -window-maximized=false -window-size=(986, 600) - -[org/gnome/clocks/state/window] -maximized=false -panel-id='world' -size=(870, 690) - -[org/gnome/control-center] -last-panel='system' -window-state=(980, 640, true) - -[org/gnome/desktop/app-folders] -folder-children=['Utilities', 'YaST', 'Pardus'] - -[org/gnome/desktop/app-folders/folders/Pardus] -categories=['X-Pardus-Apps'] -name='X-Pardus-Apps.directory' -translate=true - -[org/gnome/desktop/app-folders/folders/Utilities] -apps=['org.gnome.baobab.desktop', 'org.gnome.DiskUtility.desktop', 'org.gnome.seahorse.Application.desktop', 'org.gnome.Logs.desktop', 'avahi-discover.desktop'] -categories=['X-GNOME-Utilities'] -excluded-apps=['org.gnome.Console.desktop', 'org.gnome.Evince.desktop', 'org.gnome.Characters.desktop', 'nm-connection-editor.desktop', 'org.gnome.font-viewer.desktop'] -name='X-GNOME-Utilities.directory' -translate=true - -[org/gnome/desktop/app-folders/folders/YaST] -categories=['X-SuSE-YaST'] -name='suse-yast.directory' -translate=true - -[org/gnome/desktop/background] -color-shading-type='solid' -picture-options='zoom' -picture-uri='file:///usr/share/backgrounds/macosw/MacVentura-Light.jpg' -picture-uri-dark='file:///usr/share/backgrounds/macosw/MacVentura-Dark.jpg' -primary-color='#000000000000' -secondary-color='#000000000000' - -[org/gnome/desktop/input-sources] -sources=[('xkb', 'us')] -xkb-options=@as [] - -[org/gnome/desktop/interface] -color-scheme='default' -cursor-theme='WhiteSur-cursors' -document-font-name='SF Pro Display 10' -enable-animations=true -font-hinting='full' -font-name='SF Pro Display 10' -gtk-theme='WhiteSur-Light' -icon-theme='WhiteSur-light' -monospace-font-name='MesloLGS NF 13' -toolkit-accessibility=false - -[org/gnome/desktop/notifications] -application-children=['gnome-power-panel', 'org-gnome-calendar', 'firefox', 'com-mattjakeman-extensionmanager', 'org-gnome-settings'] - -[org/gnome/desktop/notifications/application/com-mattjakeman-extensionmanager] -application-id='com.mattjakeman.ExtensionManager.desktop' - -[org/gnome/desktop/notifications/application/firefox] -application-id='firefox.desktop' - -[org/gnome/desktop/notifications/application/gnome-power-panel] -application-id='gnome-power-panel.desktop' - -[org/gnome/desktop/notifications/application/org-gnome-calendar] -application-id='org.gnome.Calendar.desktop' - -[org/gnome/desktop/notifications/application/org-gnome-settings] -application-id='org.gnome.Settings.desktop' - -[org/gnome/desktop/peripherals/keyboard] -numlock-state=true - -[org/gnome/desktop/peripherals/touchpad] -two-finger-scrolling-enabled=true - -[org/gnome/desktop/privacy] -old-files-age=uint32 30 -recent-files-max-age=-1 - -[org/gnome/desktop/screensaver] -color-shading-type='solid' -picture-options='zoom' -picture-uri='file:///usr/share/backgrounds/macosw/MacVentura-Light.jpg' -primary-color='#000000000000' -secondary-color='#000000000000' - -[org/gnome/desktop/search-providers] -disabled=['org.gnome.Characters.desktop', 'org.gnome.seahorse.Application.desktop'] -sort-order=['org.gnome.Contacts.desktop', 'org.gnome.Documents.desktop', 'org.gnome.Nautilus.desktop'] - -[org/gnome/desktop/session] -idle-delay=uint32 300 - -[org/gnome/desktop/wm/preferences] -button-layout='close,maximize,minimize:' - -[org/gnome/evolution-data-server] -migrated=true - -[org/gnome/file-roller/listing] -list-mode='as-folder' -name-column-width=184 -show-path=false -sort-method='name' -sort-type='ascending' - -[org/gnome/file-roller/ui] -sidebar-width=200 -window-height=480 -window-width=600 - -[org/gnome/gnome-system-monitor] -show-dependencies=false -show-whose-processes='user' - -[org/gnome/gnome-system-monitor/disktreenew] -col-6-visible=true -col-6-width=0 -columns-order=[5] -sort-col=1 -sort-order=0 - -[org/gnome/maps] -last-viewed-location=[0.0, 0.0] -map-type='MapsStreetSource' -transportation-type='pedestrian' -window-maximized=false -window-size=[682, 493] -zoom-level=2 - -[org/gnome/mutter] -center-new-windows=true -overlay-key='Super_L' - -[org/gnome/mutter/keybindings] -toggle-tiled-left=@as [] -toggle-tiled-right=@as [] - -[org/gnome/nautilus/icon-view] -default-zoom-level='medium' - -[org/gnome/nautilus/preferences] -default-folder-viewer='icon-view' -migrated-gtk-settings=true -search-filter-time-type='last_modified' - -[org/gnome/nautilus/window-state] -initial-size=(770, 513) -maximized=false - -[org/gnome/nm-applet/eap/b2694852-f55e-3421-a3a8-3c368465ecb2] -ignore-ca-cert=false -ignore-phase2-ca-cert=false - -[org/gnome/pomodoro/state] -timer-date='2024-05-24T01:55:24+0000' -timer-elapsed=0.0 -timer-paused=false -timer-score=0.0 -timer-state='null' -timer-state-date='2024-05-24T01:55:24+0000' -timer-state-duration=0.0 - -[org/gnome/portal/filechooser/gnome-background-panel] -last-folder-path='/usr/share/backgrounds/macosw' - -[org/gnome/settings-daemon/plugins/power] -sleep-inactive-ac-timeout=3600 -sleep-inactive-ac-type='nothing' - -[org/gnome/shell] -app-picker-layout=[{'display-im6.q16.desktop': <{'position': <0>}>, 'nm-connection-editor.desktop': <{'position': <1>}>, 'org.gnome.tweaks.desktop': <{'position': <2>}>, 'gnome-language-selector.desktop': <{'position': <3>}>, 'org.gnome.SystemMonitor.desktop': <{'position': <4>}>, 'org.gnome.clocks.desktop': <{'position': <5>}>, 'update-manager.desktop': <{'position': <6>}>, 'gnome-session-properties.desktop': <{'position': <7>}>, 'org.gnome.font-viewer.desktop': <{'position': <8>}>, 'software-properties-drivers.desktop': <{'position': <9>}>, 'org.gnome.Evince.desktop': <{'position': <10>}>, 'org.gnome.Characters.desktop': <{'position': <11>}>, 'software-properties-gtk.desktop': <{'position': <12>}>, 'org.gnome.Contacts.desktop': <{'position': <13>}>}, {'Utilities': <{'position': <0>}>, 'org.gnome.PowerStats.desktop': <{'position': <1>}>, 'yelp.desktop': <{'position': <2>}>, 'ca.desrt.dconf-editor.desktop': <{'position': <3>}>, 'org.gnome.Console.desktop': <{'position': <4>}>, 'com.mattjakeman.ExtensionManager.desktop': <{'position': <5>}>, 'snap-store_snap-store.desktop': <{'position': <6>}>, 'org.gnome.Connections.desktop': <{'position': <7>}>, 'firefox_firefox.desktop': <{'position': <8>}>, 'firmware-updater_firmware-updater.desktop': <{'position': <9>}>, 'org.gnome.Pomodoro.desktop': <{'position': <10>}>}] -disable-user-extensions=false -disabled-extensions=['ding@rastersoft.com', 'ubuntu-dock@ubuntu.com', 'tiling-assistant@ubuntu.com', 'azclock@azclock.gitlab.com', 'quick-settings-tweaks@qwreey', 'quick-settings-avatar@d-go', 'arcmenu@arcmenu.com', 'dash2dock-lite@icedman.github.com', 'openbar@neuromorph', 'compact-quick-settings@gnome-shell-extensions.mariospr.org', 'apps-menu@gnome-shell-extensions.gcampax.github.com', 'ubuntu-appindicators@ubuntu.com'] -enabled-extensions=['SettingsCenter@lauinger-clan.de', 'windowgestures@extension.amarullz.com', 'appindicatorsupport@rgcjonas.gmail.com', 'compiz-alike-magic-lamp-effect@hermes83.github.com', 'CoverflowAltTab@palatis.blogspot.com', 'dash-to-dock@micxgx.gmail.com', 'date-menu-formatter@marcinjakubowski.github.com', 'desktop-cube@schneegans.github.com', 'gsconnect@andyholmes.github.io', 'logomenu@aryan_k', 'media-progress@krypion17', 'order-extensions@wa4557.github.com', 'nightthemeswitcher@romainvigier.fr', 'moveclock@kuvaus.org', 'places-menu@gnome-shell-extensions.gcampax.github.com', 'power-profile-indicator@laux.wtf', 'search-light@icedman.github.com', 'user-theme@gnome-shell-extensions.gcampax.github.com', 'just-perfection-desktop@just-perfection', 'blur-my-shell@aunetx', 'appmenu-is-back@fthx', 'pomodoro@arun.codito.in'] -favorite-apps=['org.gnome.Nautilus.desktop', 'org.gnome.Maps.desktop', 'org.gnome.Software.desktop', 'org.gnome.Weather.desktop', 'org.gnome.eog.desktop', 'org.gnome.TextEditor.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.gedit.desktop', 'org.gnome.Calculator.desktop', 'org.gnome.Settings.desktop'] -last-selected-power-profile='power-saver' -welcome-dialog-last-shown-version='46.0' - -[org/gnome/shell/extensions/Logo-menu] -hide-icon-shadow=false -menu-button-extensions-app='com.mattjakeman.ExtensionManager.desktop' -menu-button-icon-image=0 -menu-button-icon-size=20 -show-activities-button=true -show-lockscreen=true -show-power-options=true -symbolic-icon=true -use-custom-icon=false - -[org/gnome/shell/extensions/blur-my-shell] -pipelines={'pipeline_default': {'name': <'Default'>, 'effects': <[<{'type': <'native_static_gaussian_blur'>, 'id': <'effect_000000000000'>, 'params': <{'radius': <30>, 'brightness': <0.59999999999999998>}>}>]>}, 'pipeline_default_rounded': {'name': <'Default rounded'>, 'effects': <[<{'type': <'native_static_gaussian_blur'>, 'id': <'effect_000000000001'>, 'params': <{'radius': <30>, 'brightness': <0.59999999999999998>}>}>, <{'type': <'corner'>, 'id': <'effect_000000000002'>, 'params': <{'radius': <30>, 'corners_top': , 'corners_bottom': }>}>]>}} -settings-version=2 - -[org/gnome/shell/extensions/blur-my-shell/appfolder] -blur=true -brightness=0.59999999999999998 -sigma=30 - -[org/gnome/shell/extensions/blur-my-shell/applications] -blur=true -whitelist=['org.gnome.Nautilus', 'org.gnome.Console', 'org.gnome.Calculator'] - -[org/gnome/shell/extensions/blur-my-shell/dash-to-dock] -blur=true -brightness=0.59999999999999998 -override-background=true -pipeline='pipeline_default_rounded' -sigma=30 -static-blur=true -style-dash-to-dock=0 -unblur-in-overview=false - -[org/gnome/shell/extensions/blur-my-shell/dash-to-panel] -blur-original-panel=true - -[org/gnome/shell/extensions/blur-my-shell/lockscreen] -pipeline='pipeline_default' - -[org/gnome/shell/extensions/blur-my-shell/overview] -blur=true -pipeline='pipeline_default' -style-components=0 - -[org/gnome/shell/extensions/blur-my-shell/panel] -brightness=0.59999999999999998 -force-light-text=true -override-background=true -override-background-dynamically=false -pipeline='pipeline_default' -sigma=30 -static-blur=true -style-panel=0 - -[org/gnome/shell/extensions/blur-my-shell/screenshot] -pipeline='pipeline_default' - -[org/gnome/shell/extensions/blur-my-shell/window-list] -brightness=0.59999999999999998 -sigma=30 - -[org/gnome/shell/extensions/coverflowalttab] -animation-time=0.5 -blur-radius=0 -current-workspace-only='all' -enforce-primary-monitor=true -hide-panel=true -highlight-mouse-over=false -icon-has-shadow=false -icon-style='Classic' -invert-swipes=true -overlay-icon-opacity=0.75 -perspective-correction-method='Adjust Angles' -preview-to-monitor-ratio=0.52300000000000002 -randomize-animation-times=false -switch-application-behaves-like-switch-windows=false -switch-per-monitor=true -switcher-background-color=(0.031372549019607843, 0.37647058823529411, 0.94901960784313721) -switcher-looping-method='Carousel' -switcher-style='Coverflow' -use-glitch-effect=false -use-tint=false - -[org/gnome/shell/extensions/dash-to-dock] -always-center-icons=false -apply-custom-theme=true -autohide=true -autohide-in-fullscreen=true -background-color='rgb(255,255,255)' -background-opacity=0.80000000000000004 -click-action='focus-minimize-or-previews' -custom-background-color=false -custom-theme-shrink=true -dash-max-icon-size=48 -disable-overview-on-startup=true -dock-fixed=false -dock-position='BOTTOM' -extend-height=false -height-fraction=0.90000000000000002 -icon-size-fixed=true -intellihide=true -intellihide-mode='MAXIMIZED_WINDOWS' -middle-click-action='launch' -preferred-monitor=-2 -preferred-monitor-by-connector='Virtual-1' -preview-size-scale=0.29999999999999999 -running-indicator-style='DOTS' -shift-click-action='minimize' -shift-middle-click-action='launch' -show-apps-at-top=true -show-mounts-network=true -transparency-mode='DYNAMIC' - -[org/gnome/shell/extensions/date-menu-formatter] -apply-all-panels=true -formatter='01_luxon' -pattern='EEE, d, hh:mm a' -text-align='right' -use-default-calendar=true - -[org/gnome/shell/extensions/ding] -check-x11wayland=true - -[org/gnome/shell/extensions/gsconnect] -id='9f582610-566c-47c5-b768-9b7b0fd82196' -name='linuxscoop' - -[org/gnome/shell/extensions/just-perfection] -clock-menu-position=0 -clock-menu-position-offset=0 -controls-manager-spacing-size=0 -notification-banner-position=2 -osd-position=8 -panel-button-padding-size=11 -panel-indicator-padding-size=11 -search=true -startup-status=0 -theme=false -workspaces-in-app-grid=false - -[org/gnome/shell/extensions/moveclock] -clock-before-statusmenu=false - -[org/gnome/shell/extensions/ncom/github/hermes83/compiz-alike-magic-lamp-effect] -effect='default' - -[org/gnome/shell/extensions/nightthemeswitcher/commands] -enabled=true - -[org/gnome/shell/extensions/nightthemeswitcher/time] -manual-schedule=true -nightthemeswitcher-ondemand-keybinding=['t'] - -[org/gnome/shell/extensions/order-icons] -icons-blacklist=['ArcMenu'] -order-icons-center=@as [] -order-icons-left=['LogoMenu', 'activities', 'places-menu', 'appmenu-indicator'] -order-icons-right=['686fd560-1c6c-11ef-823f-55c5a292da21', 'd343a980-1c6b-11ef-a0d7-896d89a1cdfb', 'c863bc00-1bd8-11ef-b856-33645d49c08c', 'a8aca1b0-1bd3-11ef-9fe0-7143877a2ff4', 'gnome-pomodoro', 'livepatch', 'software-update-available', 'a11y', 'keyboard', 'dwellClick', 'screenSharing', 'screenRecording', 'quickSettings', 'dateMenu'] - -[org/gnome/shell/extensions/search-light] -blur-background=true -blur-brightness=0.59999999999999998 -blur-sigma=30.0 -border-radius=3.384297520661157 -border-thickness=0 -currency-converter=true -entry-font-size=1 -monitor-count=1 -popup-at-cursor-monitor=true -preferred-monitor=0 -scale-height=0.10000000000000001 -scale-width=0.0 -secondary-shortcut-search=['space'] -shortcut-search=['space'] -show-panel-icon=false -unit-converter=true - -[org/gnome/shell/extensions/tiling-assistant] -active-window-hint-color='rgb(211,70,21)' -last-version-installed=46 -tiling-popup-all-workspace=true - -[org/gnome/shell/extensions/user-theme] -name='WhiteSur-Light' - -[org/gnome/shell/extensions/windowgestures] -three-finger=true -ui-theme=0 - -[org/gnome/shell/weather] -automatic-location=true -locations=[<(uint32 2, <('New York City, Central Park', 'KNYC', false, [(0.71180344078725644, -1.2909618758762367)], @a(dd) [])>)>] - -[org/gnome/shell/world-clocks] -locations=@av [] - -[org/gnome/software] -check-timestamp=int64 1716508346 -flatpak-purge-timestamp=int64 1716096087 - -[org/gnome/terminal/legacy] -theme-variant='system' - -[org/gnome/terminal/legacy/profiles:] -default='7b4df471-ff52-4b7f-b8e7-0049c20e0a83' -list=['57fdd101-b1ed-4722-8584-7d69b977180b', '7b4df471-ff52-4b7f-b8e7-0049c20e0a83'] - -[org/gnome/terminal/legacy/profiles:/:57fdd101-b1ed-4722-8584-7d69b977180b] -allow-bold=true -background-color='#181816161616' -background-transparency-percent=7 -bold-color='#C5C5C9C9C5C5' -bold-color-same-as-fg=true -cursor-background-color='#C8C8C0C09393' -cursor-colors-set=true -cursor-foreground-color='#181816161616' -custom-command='/bin/zsh' -font='MesloLGS NF 10' -foreground-color='#C5C5C9C9C5C5' -login-shell=false -palette=['#0D0D0C0C0C0C', '#C4C474746E6E', '#8A8A9A9A7B7B', '#C4C4B2B28A8A', '#8B8BA4A4B0B0', '#A2A29292A3A3', '#8E8EA4A4A2A2', '#C8C8C0C09393', '#A6A6A6A69C9C', '#E4E468687676', '#8787A9A98787', '#E6E6C3C38484', '#7F7FB4B4CACA', '#93938A8AA9A9', '#7A7AA8A89F9F', '#C5C5C9C9C5C5'] -use-custom-command=true -use-system-font=false -use-theme-background=false -use-theme-colors=true -use-theme-transparency=false -use-transparent-background=true -visible-name='Kanagawa Dragon' - -[org/gnome/terminal/legacy/profiles:/:7b4df471-ff52-4b7f-b8e7-0049c20e0a83] -allow-bold=true -background-color='#1F1F1F1F2828' -background-transparency-percent=4 -bold-color='#DCDCD7D7BABA' -bold-color-same-as-fg=true -cursor-background-color='#DCDCD7D7BABA' -cursor-colors-set=true -cursor-foreground-color='#1F1F1F1F2828' -custom-command='/bin/zsh' -font='MesloLGS NF 10' -foreground-color='#DCDCD7D7BABA' -login-shell=false -palette=['#090906061818', '#C3C340404343', '#767694946A6A', '#C0C0A3A36E6E', '#7E7E9C9CD8D8', '#95957F7FB8B8', '#6A6A95958989', '#DCDCD7D7BABA', '#727271716969', '#E8E824242424', '#9898BBBB6C6C', '#E6E6C3C38484', '#7F7FB4B4CACA', '#93938A8AA9A9', '#7A7AA8A89F9F', '#C8C8C0C09393'] -use-custom-command=true -use-system-font=false -use-theme-background=false -use-theme-colors=false -use-theme-transparency=false -use-transparent-background=true -visible-name='Kanagawa' - -[org/gnome/terminal/legacy/profiles:/:cc6d05ce-8deb-4aec-b4b8-95c0b18e29d1] -allow-bold=true -use-theme-background=false - -[org/gtk/gtk4/settings/color-chooser] -selected-color=(true, 1.0, 1.0, 1.0, 1.0) - -[org/gtk/gtk4/settings/file-chooser] -date-format='regular' -location-mode='path-bar' -show-hidden=true -sidebar-width=140 -sort-column='name' -sort-directories-first=true -sort-order='ascending' -type-format='category' -view-type='list' -window-size=(801, 822) diff --git a/gui/gnome/autocustom-gnome-macos/conf/neofetch/config.conf b/gui/gnome/autocustom-gnome-macos/conf/neofetch/config.conf deleted file mode 100644 index ad11646b..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/neofetch/config.conf +++ /dev/null @@ -1,76 +0,0 @@ -print_info() { - -#info "\e[31m " users - info "\e[31m " kernel - info "\e[31m " uptime - info "\e[33m " packages - info "\e[33m " wm - info "\e[34m " shell - #info "\e[33m塞" memory -} - -kernel_shorthand="off" -distro_shorthand="off" -os_arch="off" -uptime_shorthand="on" -memory_percent="off" -memory_unit="mib" -package_managers="on" -shell_path="on" -shell_version="off" -refresh_rate="off" -de_version="on" -colors=(distro) -bold="on" -underline_enabled="on" -underline_char="─" -separator=" •" - -color_blocks="on" -block_width=3 -block_height=1 -col_offset="auto" -block_range=(0 7) - -bar_char_elapsed="-" -bar_char_total="=" -bar_border="on" -bar_length=15 -bar_color_elapsed="distro" -bar_color_total="distro" - -cpu_display="off" -memory_display="off" -battery_display="off" -disk_display="off" - - -# Backend Settings - -image_backend="ascii" -image_source="$HOME/.config/neofetch/idk.txt" - -# Ascii Options -ascii_distro="arch_small" -ascii_colors=(distro) -ascii_bold="on" - -# Image Options -image_loop="off" -thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch" -crop_mode="normal" -crop_offset="center" -image_size="auto" -# Gap between image and text -gap=-2 -# Image offsets -# Only works with the w3m backend. -yoffset=0 -xoffset=0 -# Image background color -# Only works with the w3m backend. -background_color= - - -# Misc -stdout="off" diff --git a/gui/gnome/autocustom-gnome-macos/conf/neofetch/idk.txt b/gui/gnome/autocustom-gnome-macos/conf/neofetch/idk.txt deleted file mode 100644 index 960ead2c..00000000 --- a/gui/gnome/autocustom-gnome-macos/conf/neofetch/idk.txt +++ /dev/null @@ -1,6 +0,0 @@ - \033[91m⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ - \033[91m⣿⣿ ⣿⣿ - \033[93m⣿⣿ ⣿ ⣿ ⣿⣿ - \033[93m⣿⣿ ⣿ ⣿ ⣿⣿ - \033[94m⣿⣿ ⣿ ⣿ ⣿⣿ - \033[94m⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ diff --git a/gui/gnome/autocustom-gnome-macos/install_fedora40.sh b/gui/gnome/autocustom-gnome-macos/install_fedora40.sh deleted file mode 100644 index 41dde528..00000000 --- a/gui/gnome/autocustom-gnome-macos/install_fedora40.sh +++ /dev/null @@ -1,226 +0,0 @@ -#!/bin/bash -# -# Script Name: install_fedora.sh -# Version : 1.0 -# Description: Installation script auto customization -# GNOME 46 Look Like macOS on Fedora 40 -# -# For Linux : Fedora 40 -# For Desktop Environment : GNOME Shell 46 -# Author: linuxscoop -# Youtube: https://youtube.com/user/linuxscoop -# Created: May 20, 2024 -# Last Modified: June 07, 2024 -# -# Update the system -update_system() { - clear - echo "Updating your system with new packages..." - sudo dnf update -y -} - -# Install command line apps and dependencies -install_apps_and_dependencies() { - clear - echo "Installing command line apps and dependencies..." - sudo dnf install -y curl \ - rsync \ - git \ - sassc \ - openssl \ - gnome-tweaks -} - -# Install GNOME apps and dependencies -install_gnome_apps() { - clear - echo "Installing GNOME apps and dependencies..." - sudo dnf install -y gnome-weather \ - gnome-maps \ - gnome-audio \ - gnome-calendar \ - gnome-clocks \ - gnome-connections \ - gnome-console \ - gnome-contacts \ - gnome-music \ - vlc \ - gnome-shell-extension-pomodoro -} - -# Install WhiteSur GTK theme and configure it -install_whitesur_gtk_theme() { - clear - echo "Installing WhiteSur GTK theme..." - mkdir -p src && cd src/ || { echo "Failed to create or enter src directory"; exit 1; } - if [ ! -d "WhiteSur-gtk-theme" ]; then - git clone https://github.com/vinceliuice/WhiteSur-gtk-theme.git || { echo "Failed to clone WhiteSur-gtk-theme repository"; exit 1; } - fi - cd WhiteSur-gtk-theme/ || { echo "Failed to enter WhiteSur-gtk-theme directory"; exit 1; } - ./install.sh -l -c Light -c Dark -s 180 -m || { echo "Failed to execute install.sh"; exit 1; } - ./tweaks.sh -d || { echo "Failed to execute tweaks.sh"; exit 1; } - cd ../../ || { echo "Failed to return to the previous directory"; exit 1; } - ln -sf "$HOME/.config/gtk-4.0/gtk-Light.css" "$HOME/.config/gtk-4.0/gtk.css" - echo "WhiteSur GTK theme installation completed." -} - -# Install WhiteSur icon theme -install_whitesur_icon_theme() { - clear - echo "Installing WhiteSur icon theme..." - cd src/ || { echo "Failed to enter src directory"; exit 1; } - if [ ! -d "WhiteSur-icon-theme" ]; then - git clone https://github.com/vinceliuice/WhiteSur-icon-theme.git || { echo "Failed to clone WhiteSur-icon-theme repository"; exit 1; } - fi - cd WhiteSur-icon-theme/ || { echo "Failed to enter WhiteSur-icon-theme directory"; exit 1; } - ./install.sh -a -b || { echo "Failed to execute install.sh"; exit 1; } - cd ../../ || { echo "Failed to return to the previous directory"; exit 1; } - echo "WhiteSur icon theme installation completed." -} - -# Install WhiteSur Firefox theme -install_whitesur_firefox_theme() { - clear - echo "Installing WhiteSur Firefox theme..." - mkdir -p src && cd src/ || { echo "Failed to create or enter src directory"; exit 1; } - if [ ! -d "WhiteSur-firefox-theme" ]; then - git clone https://github.com/vinceliuice/WhiteSur-firefox-theme.git || { echo "Failed to clone WhiteSur-firefox-theme repository"; exit 1; } - fi - cd WhiteSur-firefox-theme/ || { echo "Failed to enter WhiteSur-firefox-theme directory"; exit 1; } - ./install.sh -m || { echo "Failed to execute install.sh"; exit 1; } - cd ../../ || { echo "Failed to return to the previous directory"; exit 1; } - echo "WhiteSur Firefox theme installation completed." -} - -# Install cursors theme -install_cursors_theme() { - clear - echo "Installing cursors theme..." - if [ -d $HOME/.icons ]; then - cp -af res/WhiteSur-cursors/ $HOME/.icons/ - else - mkdir $HOME/.icons - cp -af res/WhiteSur-cursors/ $HOME/.icons/ - fi -} - -# Install fonts and wallpapers -install_fonts_and_wallpapers() { - clear - echo "Installing fonts and wallpapers..." - cp -af res/fonts/ $HOME/.local/share/ - sudo cp -af res/macosw/ /usr/share/backgrounds/ - sudo chmod 755 /usr/share/backgrounds/macosw - sudo chmod 644 /usr/share/backgrounds/macosw/*.* -} - -# Install GNOME shell extensions -install_gnome_shell_extensions() { - clear - echo "Installing GNOME shell extensions..." - if [ -d $HOME/.local/share/gnome-shell/extensions ]; then - cp -af res/extensions/* $HOME/.local/share/gnome-shell/extensions/ - else - mkdir -p $HOME/.local/share/gnome-shell/extensions - cp -af res/extensions/* $HOME/.local/share/gnome-shell/extensions/ - fi -} - -# Install Cava, Neofetch and their configurations -install_cava_neofetch() { - clear - echo "Installing Cava, Neofetch and their configurations..." - sudo dnf install -y cava neofetch - cp -af conf/cava/ $HOME/.config/ - cp -af conf/neofetch/ $HOME/.config/ -} - -# Install Oh My Zsh -install_zsh_oh_my_zsh() { - clear - echo "Installing Oh My Zsh..." - sudo dnf install -y zsh - sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" <. -*/ - -/* CoverflowAltTab::CoverflowSwitcher: - * - * Extends CoverflowAltTab::Switcher, switching tabs using a cover flow. - */ - - -import Graphene from 'gi://Graphene'; - -import {Switcher} from './switcher.js'; -const BaseSwitcher = Switcher; -import {Preview, Placement, Direction, findUpperLeftFromCenter} from './preview.js' - -const SIDE_ANGLE = 90; -const BLEND_OUT_ANGLE = 30; -const ALPHA = 1; - -function appendParams(base, extra) { - for (let key in extra) { - base[key] = extra[key]; - } -} - -export class CoverflowSwitcher extends BaseSwitcher { - constructor(...args) { - super(...args); - } - - _createPreviews() { - // TODO: Shouldn't monitor be set once per coverflow state? - let monitor = this._updateActiveMonitor(); - let currentWorkspace = this._manager.workspace_manager.get_active_workspace(); - - this._previewsCenterPosition = { - x: this.actor.width / 2, - y: this.actor.height / 2 + this._settings.offset - }; - let ratio = this._settings.preview_to_monitor_ratio; - this._xOffsetLeft = this.actor.width * (0.5 * (1 - ratio) - 0.1 * ratio) - this._xOffsetRight = this.actor.width - this._xOffsetLeft; - - for (let windowActor of global.get_window_actors()) { - let metaWin = windowActor.get_meta_window(); - let compositor = metaWin.get_compositor_private(); - if (compositor) { - let texture = compositor.get_texture(); - let width, height; - if (texture.get_size) { - [width, height] = texture.get_size(); - } else { - // TODO: Check this OK! - let preferred_size_ok; - [preferred_size_ok, width, height] = texture.get_preferred_size(); - } - - let scale = 1.0; - let previewScale = this._settings.preview_to_monitor_ratio; - let previewWidth = this.actor.width * previewScale; - let previewHeight = this.actor.height * previewScale; - if (width > previewWidth || height > previewHeight) - scale = Math.min(previewWidth / width, previewHeight / height); - - let preview = new Preview(metaWin, this, { - name: metaWin.title, - opacity: ALPHA * (!metaWin.minimized && metaWin.get_workspace() == currentWorkspace || metaWin.is_on_all_workspaces()) ? 255 : 0, - source: texture.get_size ? texture : compositor, - reactive: true, - x: metaWin.minimized ? 0 : - compositor.x - monitor.x, - y: metaWin.minimized ? 0 : - compositor.y - monitor.y, - translation_x: 0, - width: width, - height: height, - scale_x: metaWin.minimized ? 0 : 1, - scale_y: metaWin.minimized ? 0 : 1, - scale_z: metaWin.minimized ? 0 : 1, - rotation_angle_y: 0, - }); - preview.scale = scale; - preview.set_pivot_point_placement(Placement.CENTER); - preview.center_position = { - x: findUpperLeftFromCenter(width, - this._previewsCenterPosition.x), - y: findUpperLeftFromCenter(height, - this._previewsCenterPosition.y) - }; - - if (this._windows.includes(metaWin)) { - this._previews[this._windows.indexOf(metaWin)] = preview; - } - this._allPreviews.push(preview); - - this.previewActor.add_child(preview); - } - } - } - - _usingCarousel() { - return (this._parent === null && this._settings.switcher_looping_method == "Carousel"); - } - - _previewNext() { - if (this._currentIndex == this._windows.length - 1) { - this._setCurrentIndex(0); - if (this._usingCarousel()) { - this._updatePreviews(false) - } else { - this._flipStack(Direction.TO_LEFT); - } - } else { - this._setCurrentIndex(this._currentIndex + 1); - this._updatePreviews(false); - } - } - - _previewPrevious() { - if (this._currentIndex == 0) { - this._setCurrentIndex(this._windows.length-1); - if (this._usingCarousel()) { - this._updatePreviews(false) - } else { - this._flipStack(Direction.TO_RIGHT); - } - } else { - this._setCurrentIndex(this._currentIndex - 1); - this._updatePreviews(false); - } - } - - _flipStack(direction) { - //this._looping = true; - - let xOffset, angle; - this._updateActiveMonitor(); - if (direction === Direction.TO_LEFT) { - xOffset = -this._xOffsetLeft; - angle = BLEND_OUT_ANGLE; - } else { - xOffset = this._activeMonitor.width + this._xOffsetLeft; - angle = -BLEND_OUT_ANGLE; - } - - let animation_time = this._settings.animation_time * 2/3; - - for (let [i, preview] of this._previews.entries()) { - this._onFlipIn(preview, i, direction); - } - } - - _onFlipIn(preview, index, direction) { - let xOffsetStart, xOffsetEnd, angleStart, angleEnd; - let zeroIndexPreview = null; - this._updateActiveMonitor(); - - if (direction === Direction.TO_LEFT) { - xOffsetStart = this.actor.width + this._xOffsetLeft; - xOffsetEnd = this._xOffsetRight; - angleStart = -BLEND_OUT_ANGLE; - angleEnd = -SIDE_ANGLE + this._getPerspectiveCorrectionAngle(1); - } else { - xOffsetStart = -this._xOffsetLeft; - xOffsetEnd = this._xOffsetLeft; - angleStart = BLEND_OUT_ANGLE; - angleEnd = SIDE_ANGLE + this._getPerspectiveCorrectionAngle(0); - } - - //let animation_time = this._settings.animation_time * 2; - let animation_time = this._settings.animation_time * 2 * (direction === Direction.TO_RIGHT ? ((index + 1) / this._previews.length) : (1 - index / this._previews.length)); - this._updatePreview(index, zeroIndexPreview, preview, index, false, animation_time); - let translation_x; - if (direction === Direction.TO_RIGHT) { - translation_x = xOffsetStart - (this._previewsCenterPosition.x - - preview.width / 2) + 50 * (index - this._currentIndex); - } else { - translation_x = xOffsetStart - (this._previewsCenterPosition.x - + preview.width / 2) + 50 * (index - this._currentIndex); - } - let lastExtraParams = { - transition: 'userChoice', - onCompleteParams: [direction], - onComplete: this._onFlipComplete, - onCompleteScope: this - }; - this._manager.platform.tween(preview, { - transition: 'easeInOutQuint', - opacity: ALPHA * 255, - time: animation_time, - }); - this._raiseIcons(); - return; - } - - _onFlipComplete(direction) { - this._looping = false; - this._updatePreviews(false); - } - - // TODO: Remove unused direction variable - _animatePreviewToMid(preview, animation_time, extraParams = []) { - let pivot_point = preview.get_pivot_point_placement(Placement.CENTER); - let tweenParams = { - x: findUpperLeftFromCenter(preview.width, this._previewsCenterPosition.x), - y: findUpperLeftFromCenter(preview.height, this._previewsCenterPosition.y), - scale_x: preview.scale, - scale_y: preview.scale, - scale_z: preview.scale, - pivot_point: pivot_point, - translation_x: 0, - rotation_angle_y: 0, - time: animation_time, - transition: 'userChoice', - }; - appendParams(tweenParams, extraParams); - this._manager.platform.tween(preview, tweenParams); - } - - _animatePreviewToSide(preview, index, xOffset, extraParams, toChangePivotPoint = true) { - let [x, y] = preview.get_pivot_point(); - let pivot_point = new Graphene.Point({ x: x, y: y }); - let half_length = Math.floor(this._previews.length / 2); - let pivot_index = (this._usingCarousel()) ? - half_length : this._currentIndex; - if (toChangePivotPoint) { - if (index < pivot_index) { - let progress = pivot_index - index < 1 ? pivot_index - index : 1; - pivot_point = new Graphene.Point({ x: 0.5 - 0.5 * progress, y: 0.5}); - } else { - let progress = index - pivot_index < 1 ? index - pivot_index : 1; - pivot_point = new Graphene.Point({ x: 0.5 + 0.5 * progress, y: 0.5}); - } - } - let scale = Math.pow(this._settings.preview_scaling_factor, Math.abs(index - pivot_index)); - scale = scale * preview.scale; - let tweenParams = { - x: findUpperLeftFromCenter(preview.width, this._previewsCenterPosition.x), - y: findUpperLeftFromCenter(preview.height, this._previewsCenterPosition.y), - scale_x: scale, - scale_y: scale, - scale_z: scale, - pivot_point: pivot_point, - }; - if (index < pivot_index) { - tweenParams.translation_x = xOffset - (this._previewsCenterPosition.x - - preview.width / 2) + 50 * (index - pivot_index); - } else { - tweenParams.translation_x = xOffset - (this._previewsCenterPosition.x - + preview.width / 2) + 50 * (index - pivot_index); - } - appendParams(tweenParams, extraParams); - this._manager.platform.tween(preview, tweenParams); - } - - _getPerspectiveCorrectionAngle(side) { - if (this._settings.perspective_correction_method != "Adjust Angles") return 0; - if (this.num_monitors == 1) { - return 0; - } else if (this.num_monitors == 2) { - if (this.monitor_number == this.monitors_ltr[0].index) { - if (side == 0) return 508/1000 * 90; - else return 508/1000 *90; - } else { - if (side == 0) return -508/1000 * 90; - else return -508/1000 * 90; - } - } else if (this.num_monitors == 3) { - if (this.monitor_number == this.monitors_ltr[0].index) { - if (side == 0) return (666)/1000 * 90; - else return 750/1000 * 90; - } else if (this.monitor_number == this.monitors_ltr[1].index) { - return 0; - } else { - if (side == 0) return (-750)/1000 * 90; - else return -666/1000 * 90; - } - } - } - - _updatePreviews(reorder_only=false) { - if (this._previews == null) return; - let half_length = Math.floor(this._previews.length / 2); - let previews = []; - for (let [i, preview] of this._previews.entries()) { - let idx = (this._usingCarousel()) ? - (i - this._currentIndex + half_length + this._previews.length) % this._previews.length : - i; - previews.push([i, idx, preview]); - } - previews.sort((a, b) => a[1] - b[1]); - - let zeroIndexPreview = null; - for (let item of previews) { - let preview = item[2]; - let i = item[0]; - let idx = item[1]; - let animation_time = this._settings.animation_time * (this._settings.randomize_animation_times ? this._getRandomArbitrary(0.0001, 1) : 1); - zeroIndexPreview = this._updatePreview(idx, zeroIndexPreview, preview, i, reorder_only, animation_time); - this._manager.platform.tween(preview, { - opacity: ALPHA * 255, - time: this._settings.animation_time, - transition: 'easeInOutQuint', - onComplete: () => { - preview.set_reactive(true); - } - }); - } - if (zeroIndexPreview != null) zeroIndexPreview.make_bottom_layer(this.previewActor); - this._raiseIcons(); - } - - _updatePreview(idx, zeroIndexPreview, preview, i, reorder_only, animation_time) { - let half_length = Math.floor(this._previews.length / 2); - let pivot_index = (this._usingCarousel()) ? - half_length : this._currentIndex; - if (this._usingCarousel() && idx == 0) { - zeroIndexPreview = preview; - } - if (i == this._currentIndex) { - preview.make_top_layer(this.previewActor); - if (!reorder_only) { - this._animatePreviewToMid(preview, this._settings.animation_time); - } - } else if (idx < pivot_index) { - preview.make_top_layer(this.previewActor); - if (!reorder_only) { - let final_angle = SIDE_ANGLE + this._getPerspectiveCorrectionAngle(0); - let progress = pivot_index - idx < 1 ? pivot_index - idx : 1; - let center_offset = (this._xOffsetLeft + this._xOffsetRight) / 2; - this._animatePreviewToSide(preview, idx, center_offset - preview.width / 2 - progress * (center_offset - preview.width / 2 - this._xOffsetLeft), { - rotation_angle_y: progress * final_angle, - time: this.gestureInProgress ? 0 : animation_time, - transition: 'userChoice', - }); - } - } else /* i > this._currentIndex */ { - preview.make_bottom_layer(this.previewActor); - if (!reorder_only) { - let final_angle = -SIDE_ANGLE + this._getPerspectiveCorrectionAngle(1); - let progress = idx - pivot_index < 1 ? idx - pivot_index : 1; - let center_offset = (this._xOffsetLeft + this._xOffsetRight) / 2; - this._animatePreviewToSide(preview, idx, center_offset + preview.width / 2 + progress * (this._xOffsetRight - center_offset - preview.width / 2), { - rotation_angle_y: progress * final_angle, - time: this.gestureInProgress ? 0 : animation_time, - transition: 'userChoice', - }); - } - } - return zeroIndexPreview; - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/color_effect.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/color_effect.glsl deleted file mode 100755 index 4bfa8081..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/color_effect.glsl +++ /dev/null @@ -1,11 +0,0 @@ -uniform sampler2D tex; -uniform float red; -uniform float green; -uniform float blue; -uniform float blend; - -void main() { - vec4 s = texture2D(tex, cogl_tex_coord_in[0].st); - vec4 dst = vec4(red, green, blue, blend); - cogl_color_out = vec4(mix(s.rgb, dst.rgb * s.a, blend), s.a); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/color_effect.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/color_effect.js deleted file mode 100755 index 873522a0..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/color_effect.js +++ /dev/null @@ -1,176 +0,0 @@ -// This code istaken from the blur-my-shell extension - -//'use strict'; - -import Clutter from 'gi://Clutter'; -import Shell from 'gi://Shell'; -import GObject from 'gi://GObject'; -import GLib from 'gi://GLib'; - -const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'color_effect.glsl', GLib.UriFlags.NONE))[0]; - -const get_shader_source = _ => { - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - log(`[Coverflow Alt-Tab] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -/// New Clutter Shader Effect that simply mixes a color in, the class applies -/// the GLSL shader programmed into vfunc_get_static_shader_source and applies -/// it to an Actor. -/// -/// Clutter Shader Source Code: -/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c -/// -/// GJS Doc: -/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect -export const ColorEffect = new GObject.registerClass({ - GTypeName: "CoverflowAltTabColorEffect", - Properties: { - 'red': GObject.ParamSpec.double( - `red`, - `Red`, - `Red value in shader`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.4, - ), - 'green': GObject.ParamSpec.double( - `green`, - `Green`, - `Green value in shader`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.4, - ), - 'blue': GObject.ParamSpec.double( - `blue`, - `Blue`, - `Blue value in shader`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.4, - ), - 'blend': GObject.ParamSpec.double( - `blend`, - `Blend`, - `Amount of blending between the colors`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.4, - ), - } -}, class CoverflowAltTabColorShader extends Clutter.ShaderEffect { - _init(params) { - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - // initialize without color as a parameter - - let _color = params.color; - delete params.color; - - super._init(params); - - // set shader source - - this._source = get_shader_source(); - - if (this._source) - this.set_shader_source(this._source); - - // set shader color - - if (_color) - this.color = _color; - - this.update_enabled(); - } - - get red() { - return this._red; - } - - set red(value) { - if (this._red !== value) { - this._red = value; - - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); - } - } - - get green() { - return this._green; - } - - set green(value) { - if (this._green !== value) { - this._green = value; - - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); - } - } - - get blue() { - return this._blue; - } - - set blue(value) { - if (this._blue !== value) { - this._blue = value; - - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); - } - } - - get blend() { - return this._blend; - } - - set blend(value) { - if (this._blend !== value) { - this._blend = value; - - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); - } - this.update_enabled(); - } - - set color(rgba) { - let [r, g, b, a] = rgba; - this.red = r; - this.green = g; - this.blue = b; - this.blend = a; - } - - get color() { - return [this.red, this.green, this.blue, this.blend]; - } - - /// False set function, only cares about the color. Too hard to change. - set(params) { - this.color = params.color; - } - - update_enabled() { - this.set_enabled(true); - } - - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/glitch_effect.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/glitch_effect.glsl deleted file mode 100755 index 12a83eda..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/glitch_effect.glsl +++ /dev/null @@ -1,109 +0,0 @@ -// -// Description : Array and textureless GLSL 2D simplex noise function. -// Author : Ian McEwan, Ashima Arts. -// Maintainer : stegu -// Lastmod : 20110822 (ijm) -// License : Copyright (C) 2011 Ashima Arts. All rights reserved. -// Distributed under the MIT License. See LICENSE file. -// https://github.com/ashima/webgl-noise -// https://github.com/stegu/webgl-noise -// - -uniform sampler2D tex; -uniform float time; - -vec3 mod289(vec3 x) { - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - -vec2 mod289(vec2 x) { - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - -vec3 permute(vec3 x) { - return mod289(((x*34.0)+1.0)*x); -} - -float snoise(vec2 v) { - const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0 - 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) - -0.577350269189626, // -1.0 + 2.0 * C.x - 0.024390243902439); // 1.0 / 41.0 -// First corner - vec2 i = floor(v + dot(v, C.yy) ); - vec2 x0 = v - i + dot(i, C.xx); - -// Other corners - vec2 i1; - //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 - //i1.y = 1.0 - i1.x; - i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); - // x0 = x0 - 0.0 + 0.0 * C.xx ; - // x1 = x0 - i1 + 1.0 * C.xx ; - // x2 = x0 - 1.0 + 2.0 * C.xx ; - vec4 x12 = x0.xyxy + C.xxzz; - x12.xy -= i1; - -// Permutations - i = mod289(i); // Avoid truncation effects in permutation - vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) - + i.x + vec3(0.0, i1.x, 1.0 )); - - vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); - m = m*m ; - m = m*m ; - -// Gradients: 41 points uniformly over a line, mapped onto a diamond. -// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) - - vec3 x = 2.0 * fract(p * C.www) - 1.0; - vec3 h = abs(x) - 0.5; - vec3 ox = floor(x + 0.5); - vec3 a0 = x - ox; - -// Normalise gradients implicitly by scaling m -// Approximation of: m *= inversesqrt( a0*a0 + h*h ); - m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); - -// Compute final noise value at P - vec3 g; - g.x = a0.x * x0.x + h.x * x0.y; - g.yz = a0.yz * x12.xz + h.yz * x12.yw; - return 130.0 * dot(m, g); -} - -float rand(vec2 co) { - return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453); -} - -void main() { - vec2 uv = cogl_tex_coord_in[0].st; - float t = time * 2.0; - - // Create large, incidental noise waves - float noise = max(0.0, snoise(vec2(t, uv.y * 0.3)) - 0.3) * (1.0 / 0.7); - - // Offset by smaller, constant noise waves - noise = noise + (snoise(vec2(t*10.0, uv.y * 2.4)) - 0.5) * 0.15; - - // Apply the noise as x displacement for every line - float xpos = uv.x - noise * noise * 0.25; - if (xpos < 0.0) - xpos = -xpos; - if (xpos > 1.0) - xpos = 1.0 - xpos; - cogl_color_out = texture2D(tex, vec2(xpos, uv.y)); - - // Mix in some random interference for lines - cogl_color_out.rgb = mix(cogl_color_out.rgb, vec3(rand(vec2(uv.y * t))), noise * 0.3).rgb; - - // Apply a line pattern every 4 pixels - if (floor(mod(gl_FragCoord.y * 0.25, 2.0)) == 0.0) - { - cogl_color_out.rgb *= 1.0 - (0.15 * noise); - } - - // Shift green/blue channels (using the red channel) - cogl_color_out.g = mix(cogl_color_out.r, texture2D(tex, vec2(xpos + noise * 0.05, uv.y)).g, 0.25); - cogl_color_out.b = mix(cogl_color_out.r, texture2D(tex, vec2(xpos - noise * 0.05, uv.y)).b, 0.25); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/glitch_effect.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/glitch_effect.js deleted file mode 100755 index 70d1e86e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/effects/glitch_effect.js +++ /dev/null @@ -1,59 +0,0 @@ -// This code istaken from the blur-my-shell extension - -//'use strict'; - -import Clutter from 'gi://Clutter'; -import Shell from 'gi://Shell'; -import GObject from 'gi://GObject'; -import GLib from 'gi://GLib'; - -const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'glitch_effect.glsl', GLib.UriFlags.NONE))[0]; - -const get_shader_source = _ => { - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - log(`[Coverflow Alt-Tab] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -/// New Clutter Shader Effect that simply mixes a color in, the class applies -/// the GLSL shader programmed into vfunc_get_static_shader_source and applies -/// it to an Actor. -/// -/// Clutter Shader Source Code: -/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c -/// -/// GJS Doc: -/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect -export const GlitchEffect = new GObject.registerClass({ - GTypeName: "CoverflowAltTabGlitchEffect", -}, class CoverflowAltTabGlitchShader extends Clutter.ShaderEffect { - _init(params) { - super._init(params); - this._timeOffset = Math.random() * 1000000; - // set shader source - this._source = get_shader_source(); - - if (this._source) - this.set_shader_source(this._source); - - this.set_enabled(true); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - const time = this._timeOffset + GLib.get_monotonic_time() / GLib.USEC_PER_SEC; - this.set_uniform_value("time", time); - this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - - this.queue_repaint(); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/extension.js deleted file mode 100755 index b177e7d6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/extension.js +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ - -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* - * Gnome Shell extension specific routines. - * - * Create the correct manager and enable/disable it. - */ - -import * as Manager from './manager.js'; -import * as Platform from './platform.js'; -import * as Keybinder from './keybinder.js'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -let manager = null; - -export default class CoverflowAltTabExtension extends Extension { - constructor(metadata) { - super(metadata); - } - - - enable() { - if (!manager) { - /* - * As there are restricted Gnome versions the current extension support (that - * are specified in metadata.json file), only the API related to those supported - * versions must be used, not anything else. As a result, performing checks for - * keeping backward-compatiblity with old unsupported versions is a wrong - * decision. - * - * To support older versions of Gnome, first, add the version to the metadata - * file, then, if needed, include backward-compatible API here for each - * version. - */ - manager = new Manager.Manager( - new Platform.PlatformGnomeShell(this.getSettings()), - new Keybinder.Keybinder330Api() - ); - } - manager.enable(); - } - - - disable() { - if (manager) { - manager.disable(); - manager = null; - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/keybinder.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/keybinder.js deleted file mode 100755 index f735caaa..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/keybinder.js +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ - -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* CoverflowAltTab::Keybinder - * - * Originally, created to be helper classes to handle the different keybinding APIs. - */ - -import Shell from 'gi://Shell'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import {__ABSTRACT_METHOD__} from './lib.js' - -class AbstractKeybinder { - enable() { __ABSTRACT_METHOD__(this, this.enable) } - disable() { __ABSTRACT_METHOD__(this, this.disable) } -} - -export const Keybinder330Api = class Keybinder330Api extends AbstractKeybinder { - constructor(...args) { - super(...args); - - this._startAppSwitcherBind = null; - } - - enable(startAppSwitcherBind, platform) { - let mode = Shell.ActionMode ? Shell.ActionMode : Shell.KeyBindingMode; - - this._startAppSwitcherBind = startAppSwitcherBind; - - platform.addSettingsChangedCallback(this._onSettingsChanged.bind(this)); - - Main.wm.setCustomKeybindingHandler('switch-group', mode.NORMAL, startAppSwitcherBind); - Main.wm.setCustomKeybindingHandler('switch-group-backward', mode.NORMAL, startAppSwitcherBind); - } - - disable() { - let mode = Shell.ActionMode ? Shell.ActionMode : Shell.KeyBindingMode; - Main.wm.setCustomKeybindingHandler('switch-applications', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-windows', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-group', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-applications-backward', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-windows-backward', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-group-backward', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - } - - _onSettingsChanged(settings, key=null) { - let mode = Shell.ActionMode ? Shell.ActionMode : Shell.KeyBindingMode; - if (key == null || key == 'bind-to-switch-applications') { - if (settings.get_boolean('bind-to-switch-applications')) { - Main.wm.setCustomKeybindingHandler('switch-applications', mode.NORMAL, this._startAppSwitcherBind); - Main.wm.setCustomKeybindingHandler('switch-applications-backward', mode.NORMAL, this._startAppSwitcherBind); - } else { - Main.wm.setCustomKeybindingHandler('switch-applications', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-applications-backward', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - } - } - if (key == null || key == 'bind-to-switch-windows') { - if (settings.get_boolean('bind-to-switch-windows')) { - Main.wm.setCustomKeybindingHandler('switch-windows', mode.NORMAL, this._startAppSwitcherBind); - Main.wm.setCustomKeybindingHandler('switch-windows-backward', mode.NORMAL, this._startAppSwitcherBind); - } else { - Main.wm.setCustomKeybindingHandler('switch-windows', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - Main.wm.setCustomKeybindingHandler('switch-windows-backward', mode.NORMAL, Main.wm._startSwitcher.bind(Main.wm)); - } - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/lib.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/lib.js deleted file mode 100755 index 9f6a66f2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/lib.js +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (c) 2011-2012, Giovanni Campagna - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the GNOME nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// This method can be used to write a message to GNOME Shell's log. This is enhances -// the standard log() functionality by prepending the extension's name and the location -// where the message was logged. As the extensions name is part of the location, you -// can more effectively watch the log output of GNOME Shell: -// journalctl -f -o cat | grep -E 'desktop-cube|' -// This method is based on a similar script from the Fly-Pie GNOME Shell extension which -// os published under the MIT License (https://github.com/Schneegans/Fly-Pie). -export function debug(message) { - const stack = new Error().stack.split('\n'); - - // Remove debug() function call from stack. - stack.shift(); - - // Find the index of the extension directory (e.g. desktopcube@schneegans.github.com) - // in the stack entry. We do not want to print the entire absolute file path. - const extensionRoot = stack[0].indexOf('CoverflowAltTab@palatis.blogspot.com'); - - log('[' + stack[0].slice(extensionRoot) + '] ' + message); - log(new Error().stack); -} - -/** - * Make a method psuedo-abstract. - * - * @param {Object} object The current class instance, i.e. this. - * @param {Object} method The method object, e.g. this.enable. - * @return {void} - */ -export function __ABSTRACT_METHOD__(object, method) { - throw new Error( - "Abstract method " + - object.constructor.name + "." + method.name + "()" + - " not implemented" - ); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/cs/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/cs/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index c58abf68..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/cs/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/de/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/de/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index a235172f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/de/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/es/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/es/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 7d5c8c7b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/es/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/fr/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/fr/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 03b1262e..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/fr/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/it/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/it/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 3a1626d0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/it/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/ja/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/ja/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index e2161187..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/ja/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/nb_NO/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/nb_NO/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 9db68ad3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/nb_NO/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/nl/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/nl/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 014d9147..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/nl/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/pl/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/pl/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 9a9bd72a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/pl/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/pt_BR/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/pt_BR/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index c5fb78e8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/pt_BR/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/ru/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/ru/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 7901071b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/ru/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/sv/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/sv/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index ad57ac58..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/sv/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/tr/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/tr/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index ee5415da..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/tr/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/zh_CN/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/zh_CN/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 316f29b0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/zh_CN/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/zh_TW/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/zh_TW/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo deleted file mode 100755 index 69db0bab..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/locale/zh_TW/LC_MESSAGES/CoverflowAltTab@palatis.blogspot.com.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/manager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/manager.js deleted file mode 100755 index 42e86133..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/manager.js +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ - -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* CoverflowAltTab::Manager - * - * This class is a helper class to start the actual switcher. - */ - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -function sortWindowsByUserTime(win1, win2) { - let t1 = win1.get_user_time(); - let t2 = win2.get_user_time(); - return (t2 > t1) ? 1 : -1; -} - -function matchSkipTaskbar(win) { - return !win.is_skip_taskbar(); -} - -function matchWmClass(win) { - return win.get_wm_class() == this && !win.is_skip_taskbar(); -} - -function matchWorkspace(win) { - return win.get_workspace() == this && !win.is_skip_taskbar(); -} - -function matchOtherWorkspace(win) { - return win.get_workspace() != this && !win.is_skip_taskbar(); -} - -export const Manager = class Manager { - constructor(platform, keybinder) { - this.platform = platform; - this.keybinder = keybinder; - this.switcher = null; - if (global.workspace_manager && global.workspace_manager.get_active_workspace) - this.workspace_manager = global.workspace_manager; - else - this.workspace_manager = global.screen; - - if (global.display && global.display.get_n_monitors) - this.display = global.display; - else - this.display = global.screen; - } - - enable() { - this.platform.enable(); - this.keybinder.enable(this._startWindowSwitcher.bind(this), this.platform); - } - - disable() { - if (this.switcher != null) - this.switcher.destroy(); - this.platform.disable(); - this.keybinder.disable(); - } - - activateSelectedWindow(win) { - Main.activateWindow(win, global.get_current_time()); - } - - removeSelectedWindow(win) { - win.delete(global.get_current_time()); - } - - _startWindowSwitcher(display, window, binding) { - let windows = []; - let currentWorkspace = this.workspace_manager.get_active_workspace(); - let isApplicationSwitcher = false; - - // Construct a list with all windows - let windowActors = global.get_window_actors(); - for (let windowActor of windowActors) { - if (typeof windowActor.get_meta_window === "function") { - windows.push(windowActor.get_meta_window()); - } - } - - windowActors = null; - - switch (binding.get_name()) { - case 'switch-group': - // Switch between windows of same application from all workspaces - let focused = display.focus_window ? display.focus_window : windows[0]; - windows = windows.filter(matchWmClass, focused.get_wm_class()); - windows.sort(sortWindowsByUserTime); - break; - - case 'switch-applications': - case 'switch-applications-backward': - isApplicationSwitcher = !this.platform.getSettings().switch_application_behaves_like_switch_windows - default: - let currentOnly = this.platform.getSettings().current_workspace_only; - if (currentOnly === 'all-currentfirst') { - // Switch between windows of all workspaces, prefer - // those from current workspace - let wins1 = windows.filter(matchWorkspace, currentWorkspace); - let wins2 = windows.filter(matchOtherWorkspace, currentWorkspace); - // Sort by user time - wins1.sort(sortWindowsByUserTime); - wins2.sort(sortWindowsByUserTime); - windows = wins1.concat(wins2); - wins1 = []; - wins2 = []; - } else { - let filter = currentOnly === 'current' ? matchWorkspace : - matchSkipTaskbar; - // Switch between windows of current workspace - windows = windows.filter(filter, currentWorkspace); - windows.sort(sortWindowsByUserTime); - } - break; - } - - // filter by windows existing on the active monitor - if(this.platform.getSettings().switch_per_monitor) - { - windows = windows.filter ( (win) => - win.get_monitor() == Main.layoutManager.currentMonitor.index ); - } - - if (windows.length) { - let mask = binding.get_mask(); - let currentIndex = windows.indexOf(display.focus_window); - let switcher_class = this.platform.getSettings().switcher_class; - this.switcher = new switcher_class(windows, mask, currentIndex, this, null, isApplicationSwitcher, null); - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/metadata.json deleted file mode 100755 index 745ddb67..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Replacement of Alt-Tab, iterates through windows in a cover-flow manner.", - "donations": { - "github": "dsheeler", - "liberapay": "dsheeler", - "paypal": "DanielSheeler" - }, - "gettext-domain": "CoverflowAltTab@palatis.blogspot.com", - "name": "Coverflow Alt-Tab", - "settings-schema": "org.gnome.shell.extensions.coverflowalttab", - "shell-version": [ - "46" - ], - "url": "https://github.com/dmo60/CoverflowAltTab", - "uuid": "CoverflowAltTab@palatis.blogspot.com", - "version": 72 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/platform.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/platform.js deleted file mode 100755 index 3482459a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/platform.js +++ /dev/null @@ -1,685 +0,0 @@ -/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ - -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* - * CoverflowAltTab::Platform - * - * Originally, created to be helper classes to handle Gnome Shell and Cinnamon differences. - */ - -import St from 'gi://St'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import Shell from 'gi://Shell'; -import GLib from 'gi://GLib'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Background from 'resource:///org/gnome/shell/ui/background.js'; -import {__ABSTRACT_METHOD__} from './lib.js' - -import {Switcher} from './switcher.js'; -import {CoverflowSwitcher} from './coverflowSwitcher.js'; -import {TimelineSwitcher} from './timelineSwitcher.js'; - -const POSITION_TOP = 1; -const POSITION_BOTTOM = 7; -const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface'; -const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor'; - -const TRANSITION_TYPE = 'easeOutQuad'; - -const modes = [ - Clutter.AnimationMode.EASE_IN_BOUNCE, - Clutter.AnimationMode.EASE_OUT_BOUNCE, - Clutter.AnimationMode.EASE_IN_OUT_BOUNCE, - Clutter.AnimationMode.EASE_IN_BACK, - Clutter.AnimationMode.EASE_OUT_BACK, - Clutter.AnimationMode.EASE_IN_OUT_BACK, - Clutter.AnimationMode.EASE_IN_ELASTIC, - Clutter.AnimationMode.EASE_OUT_ELASTIC, - Clutter.AnimationMode.EASE_IN_OUT_ELASTIC, - Clutter.AnimationMode.EASE_IN_QUAD, - Clutter.AnimationMode.EASE_OUT_QUAD, - Clutter.AnimationMode.EASE_IN_OUT_QUAD, - Clutter.AnimationMode.EASE_IN_CUBIC, - Clutter.AnimationMode.EASE_OUT_CUBIC, - Clutter.AnimationMode.EASE_IN_OUT_CUBIC, - Clutter.AnimationMode.EASE_IN_QUART, - Clutter.AnimationMode.EASE_OUT_QUART, - Clutter.AnimationMode.EASE_IN_OUT_QUART, - Clutter.AnimationMode.EASE_IN_QUINT, - Clutter.AnimationMode.EASE_OUT_QUINT, - Clutter.AnimationMode.EASE_IN_OUT_QUINT, - Clutter.AnimationMode.EASE_IN_SINE, - Clutter.AnimationMode.EASE_OUT_SINE, - Clutter.AnimationMode.EASE_IN_OUT_SINE, - Clutter.AnimationMode.EASE_IN_EXPO, - Clutter.AnimationMode.EASE_OUT_EXPO, - Clutter.AnimationMode.EASE_IN_OUT_EXPO, - Clutter.AnimationMode.EASE_IN_CIRC, - Clutter.AnimationMode.EASE_OUT_CIRC, - Clutter.AnimationMode.EASE_IN_OUT_CIRC, - Clutter.AnimationMode.LINEAR -]; - -function clamp(value, min, max) { - return Math.max(min, Math.min(max, value)); -} - -class AbstractPlatform { - enable() { __ABSTRACT_METHOD__(this, this.enable) } - disable() { __ABSTRACT_METHOD__(this, this.disable) } - - getWidgetClass() { __ABSTRACT_METHOD__(this, this.getWidgetClass) } - getWindowTracker() { __ABSTRACT_METHOD__(this, this.getWindowTracker) } - getPrimaryModifier(mask) { __ABSTRACT_METHOD__(this, this.getPrimaryModifier) } - - getSettings() { __ABSTRACT_METHOD__(this, this.getSettings) } - - tween(actor, params) { __ABSTRACT_METHOD__(this, this.tween) } - removeTweens(actor) { __ABSTRACT_METHOD__(this, this.removeTweens) } - - getDefaultSettings() { - return { - animation_time: 0.2, - randomize_animation_times: false, - dim_factor: 0, - title_position: POSITION_BOTTOM, - icon_style: 'Classic', - icon_has_shadow: false, - overlay_icon_opacity: 1, - text_scaling_factor: 1, - offset: 0, - hide_panel: true, - enforce_primary_monitor: true, - switcher_class: Switcher, - easing_function: 'ease-out-cubic', - current_workspace_only: '1', - switch_per_monitor: false, - preview_to_monitor_ratio: 0.5, - preview_scaling_factor: 0.75, - bind_to_switch_applications: true, - bind_to_switch_windows: true, - perspective_correction_method: "Move Camera", - highlight_mouse_over: false, - raise_mouse_over: true, - switcher_looping_method: 'Flip Stack', - switch_application_behaves_like_switch_windows: false, - blur_radius: 0, - desaturate_factor: 0.0, - tint_color: (0., 0., 0.), - switcher_background_color: (0., 0., 0.), - tint_blend: 0.0, - use_glitch_effect: false, - use_tint: false, - invert_swipes: false, - overlay_icon_size: 128, - }; - } - - initBackground() { - this._background = Meta.BackgroundActor.new_for_screen(global.screen); - this._background.hide(); - global.overlay_group.add_child(this._background); - } - - dimBackground() { - this._background.show(); - this.tween(this._background, { - dim_factor: this._settings.dim_factor, - time: this._settings.animation_time, - transition: TRANSITION_TYPE - }); - } - - removeBackground() { - global.overlay_group.remove_child(this._background); - } -} - -export class PlatformGnomeShell extends AbstractPlatform { - constructor(settings, ...args) { - super(...args); - - this._settings = null; - this._connections = null; - this._extensionSettings = settings; - this._desktopSettings = null; - this._backgroundColor = null; - this._settings_changed_callbacks = null; - this._themeContext = null; - } - - _getSwitcherBackgroundColor() { - if (this._backgroundColor === null) { - let widgetClass = this.getWidgetClass(); - let parent = new widgetClass({ visible: false, reactive: false, style_class: 'switcher-list'}); - let actor = new widgetClass({ visible: false, reactive: false, style_class: 'item-box' }); - parent.add_child(actor); - actor.add_style_pseudo_class('selected'); - Main.uiGroup.add_child(parent); - this._backgroundColor = actor.get_theme_node().get_background_color(); - Main.uiGroup.remove_child(parent); - parent = null; - let color = new GLib.Variant("(ddd)", [this._backgroundColor.red/255, this._backgroundColor.green/255, this._backgroundColor.blue/255]); - this._extensionSettings.set_value("switcher-background-color", color); - } - return this._backgroundColor; - } - - enable() { - this._themeContext = St.ThemeContext.get_for_stage(global.stage); - this._themeContextChangedID = this._themeContext.connect("changed", (themeContext) => { - this._backgroundColor = null; - this._getSwitcherBackgroundColor(); - }); - - this._settings_changed_callbacks = []; - - if (this._desktopSettings == null) - this._desktopSettings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA }); - - let keys = [ - "animation-time", - "randomize-animation-times", - "dim-factor", - "position", - "icon-style", - "icon-has-shadow", - "overlay-icon-size", - "overlay-icon-opacity", - "offset", - "hide-panel", - "enforce-primary-monitor", - "easing-function", - "current-workspace-only", - "switch-per-monitor", - "switcher-style", - "preview-to-monitor-ratio", - "preview-scaling-factor", - "bind-to-switch-applications", - "bind-to-switch-windows", - "perspective-correction-method", - "highlight-mouse-over", - "raise-mouse-over", - "desaturate-factor", - "blur-radius", - "switcher-looping-method", - "switch-application-behaves-like-switch-windows", - "use-tint", - "tint-color", - "tint-blend", - "switcher-background-color", - "use-glitch-effect", - "invert-swipes", - ]; - - let dkeys = [ - KEY_TEXT_SCALING_FACTOR, - ]; - - this._connections = []; - for (let key of keys) { - let bind = this._onSettingsChanged.bind(this, key); - this._connections.push(this._extensionSettings.connect('changed::' + key, bind)); - } - - this._dconnections = []; - for (let dkey of dkeys) { - let bind = this._onSettingsChanged.bind(this, dkey); - this._dconnections.push(this._desktopSettings.connect('changed::' + dkey, bind)); - } - - this._settings = this._loadSettings(); - } - - disable() { - this.showPanels(0); - if (this._connections) { - for (let connection of this._connections) { - this._extensionSettings.disconnect(connection); - } - this._connections = null; - } - if (this._dconnections) { - for (let dconnection of this._dconnections) { - this._desktopSettings.disconnect(dconnection); - } - } - this._themeContext.disconnect(this._themeContextChangedID); - this._themeContext = null; - - this._settings = null; - } - - getWidgetClass() { - return St.Widget; - } - - getWindowTracker() { - return Shell.WindowTracker.get_default(); - } - - getPrimaryModifier(mask) { - if (mask === 0) - return 0; - - let primary = 1; - while (mask > 1) { - mask >>= 1; - primary <<= 1; - } - return primary; - } - - getSettings() { - if (!this._settings) { - this._settings = this._loadSettings(); - } - return this._settings; - } - - addSettingsChangedCallback(cb) { - cb(this._extensionSettings); - this._settings_changed_callbacks.push(cb); - } - - _onSettingsChanged(key) { - this._settings = null; - for (let cb of this._settings_changed_callbacks) { - cb(this._extensionSettings, key); - } - } - - - _loadSettings() { - try { - let settings = this._extensionSettings; - let dsettings = this._desktopSettings; - - return { - animation_time: settings.get_double("animation-time"), - randomize_animation_times: settings.get_boolean("randomize-animation-times"), - dim_factor: clamp(settings.get_double("dim-factor"), 0, 1), - title_position: (settings.get_string("position") == 'Top' ? POSITION_TOP : POSITION_BOTTOM), - icon_style: (settings.get_string("icon-style")), - icon_has_shadow: settings.get_boolean("icon-has-shadow"), - overlay_icon_size: clamp(settings.get_double("overlay-icon-size"), 16, 1024), - overlay_icon_opacity: clamp(settings.get_double("overlay-icon-opacity"), 0, 1), - text_scaling_factor: dsettings.get_double(KEY_TEXT_SCALING_FACTOR), - offset: settings.get_int("offset"), - hide_panel: settings.get_boolean("hide-panel"), - enforce_primary_monitor: settings.get_boolean("enforce-primary-monitor"), - easing_function: settings.get_string("easing-function"), - switcher_class: settings.get_string("switcher-style") === 'Timeline' - ? TimelineSwitcher : CoverflowSwitcher, - current_workspace_only: settings.get_string("current-workspace-only"), - switch_per_monitor: settings.get_boolean("switch-per-monitor"), - preview_to_monitor_ratio: clamp(settings.get_double("preview-to-monitor-ratio"), 0, 1), - preview_scaling_factor: clamp(settings.get_double("preview-scaling-factor"), 0, 1), - bind_to_switch_applications: settings.get_boolean("bind-to-switch-applications"), - bind_to_switch_windows: settings.get_boolean("bind-to-switch-windows"), - perspective_correction_method: settings.get_string("perspective-correction-method"), - highlight_mouse_over: settings.get_boolean("highlight-mouse-over"), - raise_mouse_over: settings.get_boolean("raise-mouse-over"), - desaturate_factor: settings.get_double("desaturate-factor") === 1.0 ? 0.999 : settings.get_double("desaturate-factor"), - blur_radius: settings.get_int("blur-radius"), - switcher_looping_method: settings.get_string("switcher-looping-method"), - switch_application_behaves_like_switch_windows: settings.get_boolean("switch-application-behaves-like-switch-windows"), - tint_color: settings.get_value("tint-color").deep_unpack(), - tint_blend: settings.get_double("tint-blend"), - switcher_background_color: settings.get_value("switcher-background-color").deep_unpack(), - use_glitch_effect: settings.get_boolean("use-glitch-effect"), - use_tint: settings.get_boolean("use-tint"), - invert_swipes: settings.get_boolean("invert-swipes"), - }; - } catch (e) { - global.log(e); - } - - return this.getDefaultSettings(); - } - - tween(actor, params) { - params.duration = params.time * 1000; - if (params.transition == 'userChoice' && this.getSettings().easing_function == 'random' || - params.transition == 'Random') { - params.mode = modes[Math.floor(Math.random()*modes.length)]; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-bounce" || - params.transition == 'easeInBounce') { - params.mode = Clutter.AnimationMode.EASE_IN_BOUNCE; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-bounce" || - params.transition == 'easeOutBounce') { - params.mode = Clutter.AnimationMode.EASE_OUT_BOUNCE; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-bounce" || - params.transition == 'easeInOutBounce') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_BOUNCE; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-back" || - params.transition == 'easeInBack') { - params.mode = Clutter.AnimationMode.EASE_IN_BACK; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-back" || - params.transition == 'easeOutBack') { - params.mode = Clutter.AnimationMode.EASE_OUT_BACK; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-back" || - params.transition == 'easeInOutBack') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_BACK; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-elastic" || - params.transition == 'easeInElastic') { - params.mode = Clutter.AnimationMode.EASE_IN_ELASTIC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-elastic" || - params.transition == 'easeOutElastic') { - params.mode = Clutter.AnimationMode.EASE_OUT_ELASTIC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-elastic" || - params.transition == 'easeInOutElastic') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_ELASTIC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-quad" || - params.transition == 'easeInQuad') { - params.mode = Clutter.AnimationMode.EASE_IN_QUAD; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-quad" || - params.transition == 'easeOutQuad') { - params.mode = Clutter.AnimationMode.EASE_OUT_QUAD; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-quad" || - params.transition == 'easeInOutQuad') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_QUAD; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-cubic" || - params.transition == 'easeInCubic') { - params.mode = Clutter.AnimationMode.EASE_IN_CUBIC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-cubic" || - params.transition == 'easeOutCubic') { - params.mode = Clutter.AnimationMode.EASE_OUT_CUBIC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-cubic" || - params.transition == 'easeInOutCubic') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_CUBIC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-quart" || - params.transition == 'easeInQuart') { - params.mode = Clutter.AnimationMode.EASE_IN_QUART; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-quart" || - params.transition == 'easeOutQuart') { - params.mode = Clutter.AnimationMode.EASE_OUT_QUART; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-quart" || - params.transition == 'easeInOutQuart') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_QUART; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-quint" || - params.transition == 'easeInQuint') { - params.mode = Clutter.AnimationMode.EASE_IN_QUINT; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-quint" || - params.transition == 'easeOutQuint') { - params.mode = Clutter.AnimationMode.EASE_OUT_QUINT; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-quint" || - params.transition == 'easeInOutQuint') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_QUINT; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-sine" || - params.transition == 'easeInSine') { - params.mode = Clutter.AnimationMode.EASE_IN_SINE; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-sine" || - params.transition == 'easeOutSine') { - params.mode = Clutter.AnimationMode.EASE_OUT_SINE; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-sine" || - params.transition == 'easeInOutSine') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_SINE; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-expo" || - params.transition == 'easeInExpo') { - params.mode = Clutter.AnimationMode.EASE_IN_EXPO; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-expo" || - params.transition == 'easeOutExpo') { - params.mode = Clutter.AnimationMode.EASE_OUT_EXPO; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-expo" || - params.transition == 'easeInOutExpo') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_EXPO; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-circ" || - params.transition == 'easeInCirc') { - params.mode = Clutter.AnimationMode.EASE_IN_CIRC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-out-circ" || - params.transition == 'easeOutCirc') { - params.mode = Clutter.AnimationMode.EASE_OUT_CIRC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-in-out-circ" || - params.transition == 'easeInOutCirc') { - params.mode = Clutter.AnimationMode.EASE_IN_OUT_CIRC; - } else if (params.transition == 'userChoice' && this.getSettings().easing_function == "ease-linear" || - params.transition == 'easeLinear') { - params.mode = Clutter.AnimationMode.LINEAR; - } else { - log("Could not find Clutter AnimationMode", params.transition, this.getSettings().easing_function); - } - - if (params.onComplete) { - if (params.onCompleteParams && params.onCompleteScope) { - params.onComplete = params.onComplete.bind(params.onCompleteScope, ...params.onCompleteParams); - } else if (params.onCompleteParams) { - params.onComplete = params.onComplete.bind(null, params.onCompleteParams); - } else if (params.onCompleteScope) { - params.onComplete = params.onComplete.bind(params.onCompleteScope); - } - } - - actor.ease(params); - } - - removeTweens(actor) { - actor.remove_all_transitions(); - } - - initBackground() { - this._backgroundGroup = new Meta.BackgroundGroup(); - Main.layoutManager.uiGroup.add_child(this._backgroundGroup); - if (this._backgroundGroup.lower_bottom) { - this._backgroundGroup.lower_bottom(); - } else { - Main.uiGroup.set_child_below_sibling(this._backgroundGroup, null); - } - - this._backgroundShade = new Clutter.Actor({ - opacity: 0, - reactive: false - }); - - let constraint = Clutter.BindConstraint.new(this._backgroundGroup, - Clutter.BindCoordinate.ALL, 0); - this._backgroundShade.add_constraint(constraint); - - let shade = new MyRadialShaderEffect({name: 'shade'}); - shade.brightness = 1; - shade.sharpness = this._settings.dim_factor; - - this._backgroundShade.add_effect(shade); - - this._backgroundGroup.add_child(this._backgroundShade); - this._backgroundGroup.set_child_above_sibling(this._backgroundShade, null); - - this._backgroundGroup.hide(); - for (let i = 0; i < Main.layoutManager.monitors.length; i++) { - new Background.BackgroundManager({ - container: this._backgroundGroup, - monitorIndex: i, - vignette: false, - }); - } - } - - hidePanels() { - let panels = this.getPanels(); - for (let panel of panels) { - try { - let panelActor = (panel instanceof Clutter.Actor) ? panel : panel.actor; - panelActor.set_reactive(false); - this.tween(panelActor, { - opacity: 0, - time: this._settings.animation_time, - transition: 'easeInOutQuint' - }); - } catch (e) { - log(e); - // ignore fake panels - } - } - } - - dimBackground() { - if (this._settings.hide_panel) { - this.hidePanels(); - } - // hide gnome-shell legacy tray - try { - if (Main.legacyTray) { - Main.legacyTray.actor.hide(); - } - } catch (e) { - // ignore missing legacy tray - } - this._backgroundGroup.show(); - this.tween(this._backgroundShade, { - opacity: 255, - time: this._settings.animation_time, - transition: 'easeInOutQuint', - }); - } - - showPanels(time) { - // panels - let panels = this.getPanels(); - for (let panel of panels){ - try { - let panelActor = (panel instanceof Clutter.Actor) ? panel : panel.actor; - panelActor.set_reactive(true); - if (this._settings.hide_panel) { - this.removeTweens(panelActor); - this.tween(panelActor, { - opacity: 255, - time: time, - transition: 'easeInOutQuint' - }); - } - } catch (e) { - //ignore fake panels - } - } - } - - lightenBackground() { - if (this._settings.hide_panel) { - this.showPanels(this._settings.animation_time); - } - // show gnome-shell legacy trayconn - try { - if (Main.legacyTray) { - Main.legacyTray.actor.show(); - } - } catch (e) { - //ignore missing legacy tray - } - - this.tween(this._backgroundShade, { - time: this._settings.animation_time * 0.95, - transition: 'easeInOutQuint', - opacity: 0, - }); - - } - - removeBackground() { - this._backgroundGroup.destroy(); - } - - getPanels() { - let panels = [Main.panel]; - if (Main.panel2) - panels.push(Main.panel2); - // gnome-shell dash - if (Main.overview._dash) - panels.push(Main.overview._dash); - return panels; - } - - -} - -const VIGNETTE_DECLARATIONS = ' \ -uniform float brightness; \n\ -uniform float vignette_sharpness; \n\ -float rand(vec2 p) { \n\ - return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453123); \n\ -} \n'; - -const VIGNETTE_CODE = ' \ -cogl_color_out.a = cogl_color_in.a; \n\ -cogl_color_out.rgb = vec3(0.0, 0.0, 0.0); \n\ -vec2 position = cogl_tex_coord_in[0].xy - 0.5; \n\ -float t = clamp(length(1.41421 * position), 0.0, 1.0); \n\ -float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t); \n\ -cogl_color_out.a *= 1.0 - pixel_brightness * brightness; \n\ -cogl_color_out.a += (rand(position) - 0.5) / 100.0; \n'; - -const MyRadialShaderEffect = GObject.registerClass({ - Properties: { - 'brightness': GObject.ParamSpec.float( - 'brightness', 'brightness', 'brightness', - GObject.ParamFlags.READWRITE, - 0, 1, 1), - 'sharpness': GObject.ParamSpec.float( - 'sharpness', 'sharpness', 'sharpness', - GObject.ParamFlags.READWRITE, - 0, 1, 0), - }, -}, class MyRadialShaderEffect extends Shell.GLSLEffect { - _init(params) { - this._brightness = undefined; - this._sharpness = undefined; - - super._init(params); - - this._brightnessLocation = this.get_uniform_location('brightness'); - this._sharpnessLocation = this.get_uniform_location('vignette_sharpness'); - - this.brightness = 1.0; - this.sharpness = 0.0; - } - - vfunc_build_pipeline() { - this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, - VIGNETTE_DECLARATIONS, VIGNETTE_CODE, true); - } - - get brightness() { - return this._brightness; - } - - set brightness(v) { - if (this._brightness === v) - return; - this._brightness = v; - this.set_uniform_float(this._brightnessLocation, - 1, [this._brightness]); - this.notify('brightness'); - } - - get sharpness() { - return this._sharpness; - } - - set sharpness(v) { - if (this._sharpness === v) - return; - this._sharpness = v; - this.set_uniform_float(this._sharpnessLocation, - 1, [this._sharpness]); - this.notify('sharpness'); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/prefs.js deleted file mode 100755 index 2509025d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/prefs.js +++ /dev/null @@ -1,641 +0,0 @@ -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* - * CoverflowAltTab - * - * Preferences dialog for "gnome-extensions prefs" tool - * - * Based on preferences in the following extensions: JustPerfection, dash2doc-lite, night theme switcher, and desktop cube - * - */ -import Adw from 'gi://Adw'; -import Gdk from 'gi://Gdk'; -import GLib from 'gi://GLib'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; - -import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js' - -const easing_options = [ - { - id: 'ease-linear', name: 'easeLinear' - }, { - id: 'ease-in-quad', name: "easeInQuad" - }, { - id: 'ease-out-quad', name: "easeOutQuad" - }, { - id: 'ease-in-out-quad', name: "easeInOutQuad" - }, { - id: 'ease-in-cubic', name: "easeInCubic" - }, { - id: 'ease-out-cubic', name: "easeOutCubic" - }, { - id: 'ease-in-out-cubic', name: "easeInOutCubic" - }, { - id: 'ease-in-quart', name: "easeInQuart" - }, { - id: 'ease-out-quart', name: "easeOutQuart" - }, { - id: 'ease-in-out-quart', name: "easeInOutQuart" - }, { - id: 'ease-in-quint', name: "easeInQuint" - }, { - id: 'ease-out-quint', name: "easeOutQuint" - }, { - id: 'ease-in-out-quint', name: "easeInOutQuint" - }, { - id: 'ease-in-sine', name: "easeInSine" - }, { - id: 'ease-out-sine', name: "easeOutSine" - }, { - id: 'ease-in-out-sine', name: "easeInOutSine" - }, { - id: 'ease-in-expo', name: "easeInExpo" - }, { - id: 'ease-out-expo', name: "easeOutExpo" - }, { - id: 'ease-in-out-expo', name: "easeInOutExpo" - }, { - id: 'ease-in-circ', name: "easeInCirc" - }, { - id: 'ease-out-circ', name: "easeOutCirc" - }, { - id: 'ease-in-out-circ', name: "easeInOutCirc" - }, { - id: 'ease-in-back', name: "easeInBack" - }, { - id: 'ease-out-back', name: "easeOutBack" - }, { - id: 'ease-in-out-back', name: "easeInOutBack" - }, { - id: 'ease-in-elastic', name: "easeInElastic" - }, { - id: 'ease-out-elastic', name: "easeOutElastic" - }, { - id: 'ease-in-out-elastic', name: "easeInOutElastic" - }, { - id: 'ease-in-bounce', name: "easeInBounce" - }, { - id: 'ease-out-bounce', name: "easeOutBounce" - }, { - id: 'ease-in-out-bounce', name: "easeInOutBounce" - }, { - id: 'random', name: "Random" - }]; - -function getBaseString(translatedString) { - switch (translatedString) { - case _("Coverflow"): return "Coverflow"; - case _("Timeline"): return "Timeline"; - case _("Bottom"): return "Bottom"; - case _("Top"): return "Top"; - case _("Classic"): return "Classic"; - case _("Overlay"): return "Overlay"; - default: return translatedString; - } -} - -function makeResetButton() { - return new Gtk.Button({ - icon_name: "edit-clear-symbolic", - tooltip_text: _("Reset to default value"), - valign: Gtk.Align.CENTER, - }); -} - - -export default class CoverflowAltTabPreferences extends ExtensionPreferences { - constructor(metadata) { - super(metadata); - - let IconsPath = GLib.build_filenamev([this.path, 'ui', 'icons']); - let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - iconTheme.add_search_path(IconsPath); - } - - getVersionString(_page) { - return _('Version %d').format(this.metadata.version); - } - - fillPreferencesWindow(window) { - let settings = this.getSettings(); - let general_page = new Adw.PreferencesPage({ - title: _('General'), - icon_name: 'general-symbolic', - }); - - let switcher_pref_group = new Adw.PreferencesGroup({ - title: _('Switcher'), - }); - let switcher_looping_method_buttons = new Map([ [_("Flip Stack"), [[],[]]], [_("Carousel"), [[],[]]]]); - - let switcher_looping_method_row = buildRadioAdw(settings, "switcher-looping-method", switcher_looping_method_buttons, _("Looping Method"), _("How to cycle through windows.")); - switcher_pref_group.add(buildRadioAdw(settings, "switcher-style", new Map([ [_("Coverflow"), [[switcher_looping_method_row], []]], [_("Timeline"), [[],[switcher_looping_method_row]] ]]), _("Style"), _("Pick the type of switcher."))) - switcher_pref_group.add(buildSpinAdw(settings, "offset", [-500, 500, 1, 10], _("Vertical Offset"), _("Positive value moves everything down, negative up."))); - switcher_pref_group.add(buildRadioAdw(settings, "position", new Map([ [_("Bottom"), [[], []]], [_("Top"), [[],[]]]]), _("Window Title Position"), _("Place window title above or below the switcher."))); - switcher_pref_group.add(buildSwitcherAdw(settings, "enforce-primary-monitor", [], [], _("Enforce Primary Monitor"), _("Always show on the primary monitor, otherwise, show on the active monitor."))); - - switcher_pref_group.add(switcher_looping_method_row); - switcher_pref_group.add(buildSwitcherAdw(settings, "hide-panel", [], [], _("Hide Panel"), _("Hide panel when switching windows."))); - switcher_pref_group.add(buildSwitcherAdw(settings, "invert-swipes", [], [], _("Invert Swipes"), _("Swipe content instead of view."))); - let animation_pref_group = new Adw.PreferencesGroup({ - title: _('Animation'), - }); - - animation_pref_group.add(buildDropDownAdw(settings, "easing-function", easing_options, "Easing Function", "Determine how windows move.")); - animation_pref_group.add(buildRangeAdw(settings, "animation-time", [0.01, 20, 0.001, [0.5, 1, 1.5]], _("Duration [s]"), "", true)); - animation_pref_group.add(buildSwitcherAdw(settings, "randomize-animation-times", [], [], _("Randomize Durations"), _("Each animation duration assigned randomly between 0 and configured duration."))); - - let windows_pref_group = new Adw.PreferencesGroup({ - title: _('Switcher Windows'), - }); - let options = [{ - id: 'current', name: _("Current workspace only") - }, { - id: 'all', name: _("All workspaces") - }, { - id: 'all-currentfirst', name: _("All workspaces, current first") - }]; - windows_pref_group.add(buildDropDownAdw(settings, "current-workspace-only", options, _("Workspaces"), _("Switch between windows on current or on all workspaces."))); - windows_pref_group.add(buildSwitcherAdw(settings, "switch-per-monitor", [], [], _("Current Monitor"), _("Switch between windows on current monitor."))); - - let icon_pref_group = new Adw.PreferencesGroup({ - title: _("Icons"), - }); - - - let size_row = buildRangeAdw(settings, "overlay-icon-size", [16, 1024, 1, [32, 64, 128, 256, 512]], _("Overlay Icon Size"), _("Set the overlay icon size in pixels."), true); - let opacity_row = buildRangeAdw(settings, "overlay-icon-opacity", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Overlay Icon Opacity"), _("Set the overlay icon opacity."), true); - let buttons = new Map([[_("Classic"), [[],[size_row, opacity_row]]], [_("Overlay"), [[size_row, opacity_row], []]], [_("Attached"), [[size_row, opacity_row], []]]]); - let style_row = buildRadioAdw(settings, "icon-style", buttons, _("Application Icon Style")); - icon_pref_group.add(style_row); - icon_pref_group.add(size_row); - icon_pref_group.add(opacity_row); - icon_pref_group.add(buildSwitcherAdw(settings, "icon-has-shadow", [], [], _("Icon Shadow"))); - - let window_size_pref_group = new Adw.PreferencesGroup({ - title: _("Window Properties") - }); - window_size_pref_group.add(buildRangeAdw(settings, "preview-to-monitor-ratio", [0, 1, 0.001, [0.250, 0.500, 0.750]], _("Window Preview Size to Monitor Size Ratio"), _("Maximum ratio of window preview size to monitor size."), true)); - window_size_pref_group.add(buildRangeAdw(settings, "preview-scaling-factor", [0, 1, 0.001, [0.250, 0.500, 0.800]], _("Off-center Size Factor"), _("Factor by which to successively shrink previews off to the side."), true)); - - let background_application_switcher_pref_group = new Adw.PreferencesGroup({ - title: _('Application Switcher'), - }); - background_application_switcher_pref_group.add(buildSwitcherAdw(settings, "switch-application-behaves-like-switch-windows", [], [], _("Make the Application Switcher Behave Like the Window Switcher"), _("Don't group windows of the same application in a subswitcher."))); - background_application_switcher_pref_group.add(buildRangeAdw(settings, "desaturate-factor", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Desaturate"), _("Larger means more desaturation."), true)); - background_application_switcher_pref_group.add(buildSpinAdw(settings, "blur-radius", [0, 20, 1, 1], _("Blur"), _("Larger means blurrier."))); - - let color_row = new Adw.ExpanderRow({ - title: _("Tint"), - }); - background_application_switcher_pref_group.add(color_row); - - let use_tint_switch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: settings.get_boolean("use-tint"), - }); - settings.bind("use-tint", use_tint_switch, "active", Gio.SettingsBindFlags.DEFAULT); - color_row.add_suffix(use_tint_switch); - - let tint_chooser_row = new Adw.ActionRow({ - title: _("Color") - }); - let choose_tint_box = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - valign: Gtk.Align.CENTER, - }); - - tint_chooser_row.add_suffix(choose_tint_box); - color_row.add_row(tint_chooser_row); - - let color_dialog = new Gtk.ColorDialog({ - with_alpha: false, - }); - - let color_button = new Gtk.ColorDialogButton({ - valign: Gtk.Align.CENTER, - dialog: color_dialog, - }); - - let use_theme_color_button = new Gtk.Button({ - label: _("Set to Theme Color"), - valign: Gtk.Align.CENTER, - }); - - use_theme_color_button.connect('clicked', () => { - let c = settings.get_value("switcher-background-color").deep_unpack(); - let rgba = color_button.rgba; - rgba.red = c[0]; - rgba.green = c[1]; - rgba.blue = c[2]; - rgba.alpha = 1 - color_button.set_rgba(rgba); - }); - - choose_tint_box.append(use_theme_color_button); - choose_tint_box.append(color_button); - let c = settings.get_value("tint-color").deep_unpack(); - let rgba = color_button.rgba; - rgba.red = c[0]; - rgba.green = c[1]; - rgba.blue = c[2]; - rgba.alpha = 1 - color_button.set_rgba(rgba); - color_button.connect('notify::rgba', _ => { - let c = color_button.rgba; - let val = new GLib.Variant("(ddd)", [c.red, c.green, c.blue]); - settings.set_value("tint-color", val); - }); - use_tint_switch.connect('notify::active', function(widget) { - color_row.set_expanded(widget.get_active()); - }); - - let reset_button = makeResetButton(); - reset_button.connect("clicked", function (widget) { - settings.reset("use-tint"); - }); - color_row.add_suffix(reset_button); - color_row.add_row(buildRangeAdw(settings, "tint-blend", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Blend"), _("How much to blend the tint color; bigger means more tint color."), true)); - background_application_switcher_pref_group.add(buildSwitcherAdw(settings, "use-glitch-effect", [], [], _("Glitch"))); - - let background_pref_group = new Adw.PreferencesGroup({ - title: _('Background'), - }); - background_pref_group.add(buildRangeAdw(settings, "dim-factor", [0, 1, 0.001, [0.25, 0.5, 0.75]], _("Dim-factor"), _("Bigger means darker."), true)); - - let keybinding_pref_group = new Adw.PreferencesGroup({ - title: _("Keybindings"), - }); - keybinding_pref_group.add(buildSwitcherAdw(settings, "bind-to-switch-windows", [], [], _("Bind to 'switch-windows'"))); - keybinding_pref_group.add(buildSwitcherAdw(settings, "bind-to-switch-applications", [background_application_switcher_pref_group], [], _("Bind to 'switch-applications'"))); - - let pcorrection_pref_group = new Adw.PreferencesGroup({ - title: _("Perspective Correction") - }) - pcorrection_pref_group.add(buildDropDownAdw(settings, "perspective-correction-method", [ - { id: "None", name: _("None") }, - { id: "Move Camera", name: _("Move Camera") }, - { id: "Adjust Angles", name: _("Adjust Angles") }], - _("Perspective Correction"), ("Method to make off-center switcher look centered."))); - - let highlight_mouse_over_pref_group = new Adw.PreferencesGroup({ - title: _("Highlight Window Under Mouse"), - }); - window_size_pref_group.add(buildSwitcherAdw(settings, "highlight-mouse-over", [], [], _("Highlight Window Under Mouse"), _("Draw embelishment on window under the mouse to know the effects of clicking."))); - window_size_pref_group.add(buildSwitcherAdw(settings, "raise-mouse-over", [], [], _("Raise Window Under Mouse"), _("Raise the window under the mouse above all others."))); - - /*let tweaks_page = new Adw.PreferencesPage({ - title: _('Tweaks'), - icon_name: 'applications-symbolic', - }); - tweaks_page.add(pcorrection_pref_group); - tweaks_page.add(highlight_mouse_over_pref_group);*/ - - general_page.add(switcher_pref_group); - general_page.add(animation_pref_group); - general_page.add(icon_pref_group); - general_page.add(windows_pref_group); - general_page.add(window_size_pref_group); - general_page.add(background_pref_group); - general_page.add(background_application_switcher_pref_group); - general_page.add(pcorrection_pref_group); - general_page.add(keybinding_pref_group); - - let contribution_page = new Adw.PreferencesPage({ - title: _("Contribute"), - icon_name: 'contribute-symbolic', - }); - - let contribute_icon_pref_group = new Adw.PreferencesGroup(); - let icon_box = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - margin_top: 24, - margin_bottom: 24, - spacing: 18, - }); - - let icon_image = new Gtk.Image({ - icon_name: "coverflow-symbolic", - pixel_size: 128, - }); - - let label_box = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 6, - }); - - let label = new Gtk.Label({ - label: "Coverflow Alt-Tab", - wrap: true, - }); - let context = label.get_style_context(); - context.add_class("title-1"); - - let another_label = new Gtk.Label({ - label: this.getVersionString(), - }); - - let links_pref_group = new Adw.PreferencesGroup(); - let code_row = new Adw.ActionRow({ - icon_name: "code-symbolic", - title: _("Code (create pull requests, report issues, etc.)") - }); - let github_link = new Gtk.LinkButton({ - label: "Github", - uri: "https://github.com/dmo60/CoverflowAltTab", - }); - - let donate_row = new Adw.ActionRow({ - title: _("Donate"), - icon_name: "support-symbolic", - }) - let donate_link = new Gtk.LinkButton({ - label: "Liberapay", - uri: "https://liberapay.com/dsheeler/donate", - }); - - let donate_link_paypal = new Gtk.LinkButton({ - label: "PayPal", - - uri: "https://paypal.me/DanielSheeler?country.x=US&locale.x=en_US", - }); - - let donate_link_github = new Gtk.LinkButton({ - label: "Github", - - uri: "https://github.com/sponsors/dsheeler", - }); - - let translate_row = new Adw.ActionRow({ - title: _("Translate"), - icon_name: "translate-symbolic", - }) - let translate_link = new Gtk.LinkButton({ - label: "Weblate", - uri: "https://hosted.weblate.org/engage/coverflow-alt-tab/", - }); - code_row.add_suffix(github_link); - code_row.set_activatable_widget(github_link); - translate_row.add_suffix(translate_link); - translate_row.set_activatable_widget(translate_link); - donate_row.add_suffix(donate_link); - donate_row.add_suffix(donate_link_paypal); - donate_row.add_suffix(donate_link_github); - - links_pref_group.add(code_row); - links_pref_group.add(translate_row); - links_pref_group.add(donate_row); - - label_box.append(label); - label_box.append(another_label); - icon_box.append(icon_image); - icon_box.append(label_box); - contribute_icon_pref_group.add(icon_box); - - contribution_page.add(contribute_icon_pref_group); - contribution_page.add(links_pref_group) - - window.add(general_page); - // window.add(appearance_page); - window.add(contribution_page); - - window.set_search_enabled(true); - } -} - -function buildSwitcherAdw(settings, key, dependant_widgets, inverse_dependant_widgets, title, subtitle=null) { - let pref = new Adw.ActionRow({ - title: title, - }); - if (subtitle != null) { - pref.set_subtitle(subtitle); - } - - let switcher = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: settings.get_boolean(key) - }); - - switcher.expand = false; - switcher.connect('notify::active', function(widget) { - settings.set_boolean(key, widget.active); - }); - - pref.set_activatable_widget(switcher); - pref.add_suffix(switcher); - - switcher.connect('notify::active', function(widget) { - for (let dep of dependant_widgets) { - dep.set_sensitive(widget.get_active()); - } - }); - - - - for (let widget of dependant_widgets) { - widget.set_sensitive(switcher.get_active()); - } - - switcher.connect('notify::active', function(widget) { - for (let inv_dep of inverse_dependant_widgets) { - inv_dep.set_sensitive(!widget.get_active()); - } - }); - - for (let widget of inverse_dependant_widgets) { - widget.set_sensitive(!switcher.get_active()); - } - - let reset_button = makeResetButton(); - reset_button.connect("clicked", function(widget) { - settings.reset(key); - switcher.set_active(settings.get_boolean(key)); - }) - pref.add_suffix(reset_button); - return pref; -} - -function buildRangeAdw(settings, key, values, title, subtitle="", draw_value=false) { - let [min, max, step, defvs] = values; - - let pref = new Adw.ActionRow({ - title: title, }); - if (subtitle !== null && subtitle !== "") { - pref.set_subtitle(subtitle); - } - let range = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, min, max, step); - range.set_value(settings.get_double(key)); - if (draw_value) { - range.set_draw_value(true); - range.set_value_pos(Gtk.PositionType.RIGHT) - } - for (let defv of defvs) { - range.add_mark(defv, Gtk.PositionType.BOTTOM, null); - } - range.set_size_request(200, -1); - - range.connect('value-changed', function(slider) { - settings.set_double(key, slider.get_value()); - }); - - pref.set_activatable_widget(range); - pref.add_suffix(range) - - let reset_button = makeResetButton(); - reset_button.connect("clicked", function(widget) { - settings.reset(key); - range.set_value(settings.get_double(key)); - }); - pref.add_suffix(reset_button); - return pref; -} - -function buildRadioAdw(settings, key, buttons, title, subtitle=null) { - let pref = new Adw.ActionRow({ - title: title, - }); - if (subtitle != null) { - pref.set_subtitle(subtitle); - } - let hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - valign: Gtk.Align.CENTER, - }); - - let radio = new Gtk.ToggleButton(); - - let radio_for_button = {}; - for (let button_name of buttons.keys()) { - radio = new Gtk.ToggleButton({group: radio, label: button_name}); - radio_for_button[button_name] = radio; - if (getBaseString(button_name) == settings.get_string(key)) { - radio.set_active(true); - for (let pref_row of buttons.get(button_name)[0]) { - pref_row.set_sensitive(radio_for_button[button_name].get_active()); - } - for (let pref_row of buttons.get(button_name)[1]) { - pref_row.set_sensitive(!radio_for_button[button_name].get_active()); - } - } - radio.connect('toggled', function(widget) { - if (widget.get_active()) { - settings.set_string(key, getBaseString(widget.get_label())); - } - for (let pref_row of buttons.get(button_name)[0]) { - pref_row.set_sensitive(widget.get_active()); - } - for (let pref_row of buttons.get(button_name)[1]) { - pref_row.set_sensitive(!widget.get_active()); - } - }); - hbox.append(radio); - }; - - let reset_button = makeResetButton(); - reset_button.connect("clicked", function(widget) { - settings.reset(key); - for (let button of buttons.keys()) { - if (getBaseString(button) == settings.get_string(key)) { - radio_for_button[button].set_active(true); - } - } - }); - - pref.set_activatable_widget(hbox); - pref.add_suffix(hbox); - pref.add_suffix(reset_button); - return pref; -}; - -function buildSpinAdw(settings, key, values, title, subtitle=null) { - let [min, max, step, page] = values; - let pref = new Adw.ActionRow({ - title: title, - }); - if (subtitle != null) { - pref.set_subtitle(subtitle); - } - let spin = new Gtk.SpinButton({ valign: Gtk.Align.CENTER }); - spin.set_range(min, max); - spin.set_increments(step, page); - spin.set_value(settings.get_int(key)); - - spin.connect('value-changed', function(widget) { - settings.set_int(key, widget.get_value()); - }); - - pref.set_activatable_widget(spin); - pref.add_suffix(spin); - - let reset_button = makeResetButton(); - reset_button.connect("clicked", function(widget) { - settings.reset(key); - spin.set_value(settings.get_int(key)); - }); - - pref.add_suffix(reset_button); - - return pref; -} - -function buildDropDownAdw(settings, key, values, title, subtitle=null) { - let pref = new Adw.ActionRow({ - title: title, - }); - if (subtitle != null) { - pref.set_subtitle(subtitle); - } - let model = new Gtk.StringList(); - let chosen_idx = 0; - for (let i = 0; i < values.length; i++) { - let item = values[i]; - model.append(item.name); - if (item.id == settings.get_string(key)) { - chosen_idx = i; - } - } - - let chooser = new Gtk.DropDown({ - valign: Gtk.Align.CENTER, - model: model, - selected: chosen_idx, - }); - chooser.connect('notify::selected-item', function(c) { - let idx = c.get_selected(); - settings.set_string(key, values[idx].id); - }); - pref.set_activatable_widget(chooser); - pref.add_suffix(chooser); - - let reset_button = makeResetButton(); - reset_button.connect("clicked", function(widget) { - settings.reset(key); - for (let i = 0; i < values.length; i++) { - let item = values[i]; - if (item.id == settings.get_string(key)) { - chooser.set_selected(i); - break; - } - } - }); - pref.add_suffix(reset_button); - return pref; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/preview.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/preview.js deleted file mode 100755 index 86971bdf..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/preview.js +++ /dev/null @@ -1,429 +0,0 @@ -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Graphene from 'gi://Graphene'; -import St from 'gi://St'; - -/** - * Direction and Placement properties values are set to be compatible with deprecated - * Clutter.Gravity. - */ - -export class Direction {} -Direction.TO_RIGHT = 3; -Direction.TO_LEFT = 7; - -export class Placement {} -Placement.TOP = 1; -Placement.TOP_RIGHT = 2; -Placement.RIGHT = 3; -Placement.BOTTOM_RIGHT = 4; -Placement.BOTTOM = 5; -Placement.BOTTOM_LEFT = 6; -Placement.LEFT = 7; -Placement.TOP_LEFT = 8; -Placement.CENTER = 9; - -export const Preview = GObject.registerClass({ - GTypeName: "Preview", - Properties: { - 'remove_icon_opacity': GObject.ParamSpec.double( - `remove_icon_opacity`, - `Revmove Icon Opacity`, - `Icon opacity when `, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 1.0, - ) - } -}, class Preview extends Clutter.Clone { - _init(window, switcher, ...args) { - super._init(...args); - this.metaWin = window; - this.switcher = switcher; - this._icon = null; - this._highlight = null; - this._flash = null; - this._entered = false; - this._effectNames = ['blur', 'glitch', 'desaturate', 'tint'] - this._effectCounts = {}; - for (let effect_name of this._effectNames) { - this._effectCounts[effect_name] = 0; - } - } - - /** - * Make the preview above all other children layers in the given parent. - * - * @param {Object} parent The preview parent. If is not its real parent,then the - * behaviour is undefined. - * @return {void} - */ - make_top_layer(parent) { - if (this.raise_top) { - this.raise_top() - if (this._icon) this._icon.raise_top(); - } else if (parent.set_child_above_sibling) { - parent.set_child_above_sibling(this, null); - if (this._icon) parent.set_child_above_sibling(this._icon, this); - } else { - // Don't throw anything here, it may cause unstabilities - logError("No method found for making preview the top layer"); - } - } - - /** - * Make the preview below all other children layers in the given parent. - * - * @param {Object} parent The preview parent. If is not its real parent,then the - * behaviour is undefined. - * @return {void} - */ - make_bottom_layer(parent) { - if (this.lower_bottom) { - if (this._icon) this._icon.lower_bottom(); - this.lower_bottom() - } else if (parent.set_child_below_sibling) { - parent.set_child_below_sibling(this, null); - if (this._icon) parent.set_child_above_sibling(this._icon, this); - } else { - // Don't throw anything here, it may cause unstabilities - logError("No method found for making preview the bottom layer"); - } - } - - addEffect(effect_class, constructor_argument, name, parameter_name, from_param_value, param_value, duration) { - duration = 0.99 * 1000.0 * duration; - let effect_name = name + "-effect"; - let add_transition_name = effect_name + "-add"; - let remove_transition_name = effect_name + "-remove"; - let property_transition_name = `@effects.${effect_name}.${parameter_name}`; - if (this.get_transition(remove_transition_name) !== null) { - this.remove_transition(remove_transition_name); - let transition = Clutter.PropertyTransition.new(property_transition_name); - transition.progress_mode = Clutter.AnimationMode.LINEAR; - transition.duration = duration; - transition.remove_on_complete = true; - transition.set_from(this.get_effect(effect_name)[parameter_name]); - transition.set_to(param_value); - this.get_effect(effect_name)[parameter_name] = 1.0; - this.add_transition(add_transition_name, transition); - transition.connect('new-frame', (timeline, msecs) => { - this.queue_redraw(); - }); - } else if (this._effectCounts[name] == 0) { - if (this.get_transition(add_transition_name) === null) { - let transition = Clutter.PropertyTransition.new(property_transition_name); - transition.progress_mode = Clutter.AnimationMode.LINEAR; - transition.duration = duration; - transition.remove_on_complete = true; - transition.set_to(param_value); - transition.set_from(from_param_value); - this._newFrameCount = 0; - this.add_effect_with_name(effect_name, new effect_class(constructor_argument)); - this.add_transition(add_transition_name, transition); - this._effectCounts[name] = 1; - transition.connect('new-frame', (timeline, msecs) => { - this.queue_redraw(); - }); - } - } else { - this._effectCounts[name] += 1; - } - } - - removeEffect(name, parameter_name, value, duration) { - duration = 0.99 * 1000.0 * duration; - let effect_name = name + "-effect"; - let add_transition_name = effect_name + "-add"; - let remove_transition_name = effect_name + "-remove"; - let property_transition_name = `@effects.${effect_name}.${parameter_name}`; - if (this._effectCounts[name] > 0) { - if (this._effectCounts[name] == 1) { - this.remove_transition(add_transition_name); - if (this.get_transition(remove_transition_name) === null) { - let transition = Clutter.PropertyTransition.new(property_transition_name); - transition.progress_mode = Clutter.AnimationMode.LINEAR; - transition.duration = duration; - transition.remove_on_complete = true; - transition.set_from(this.get_effect(effect_name)[parameter_name]); - transition.set_to(value); - this.get_effect(effect_name)[parameter_name] = 1.0; - this.add_transition(remove_transition_name, transition); - transition.connect("completed", (trans) => { - this.remove_effect_by_name(effect_name); - this._effectCounts[name] = 0; - }); - } - } else { - this._effectCounts[name] -= 1; - } - } - } - - _pulse_highlight() { - if (this._highlight == null) return; - this._highlight.ease({ - opacity: 255, - duration: 2000, - mode: Clutter.AnimationMode.EASE_IN_OUT_QUINT, - onComplete: () => { - this._highlight.ease({ - opacity: 80, - duration: 1400, - mode: Clutter.AnimationMode.EASE_IN_OUT_QUINT, - onComplete: () => { - this._pulse_highlight(); - }, - }); - }, - }); - } - - remove_highlight() { - if (this._highlight != null) { - this._highlight.ease({ - opacity: 0, - duration: 300, - mode: Clutter.AnimationMode.EASE_IN_OUT_QUINT, - onComplete: () => { - if (this._highlight != null) { - this._highlight.destroy() - this._highlight = null; - } - }, - }); - } - if (this._flash != null) { - this._flash.destroy(); - this._flash = null; - } - } - - _getHighlightStyle(alpha) { - let bgcolor = this.switcher._getSwitcherBackgroundColor(); - let style =`background-color: rgba(${bgcolor.red}, ${bgcolor.green}, ${bgcolor.blue}, ${alpha})`; - return style; - } - - vfunc_enter_event(crossingEvent) { - if (this.switcher._animatingClosed || this._entered == true) { - return Clutter.EVENT_PROPAGATE; - } - this._entered = true; - if (this.switcher._settings.raise_mouse_over) { - this.make_top_layer(this.switcher.previewActor); - this.switcher._raiseIcons(); - } - if (this.switcher._settings.highlight_mouse_over) { - let window_actor = this.metaWin.get_compositor_private(); - if (this._highlight == null) { - this._highlight = new St.Bin({ - opacity: 0, - width: this.width, - height: this.height, - x: 0, - y: 0, - reactive: false, - }); - this._highlight.set_style(this._getHighlightStyle(0.3)); - let constraint = Clutter.BindConstraint.new(window_actor, Clutter.BindCoordinate.SIZE, 0); - this._highlight.add_constraint(constraint); - window_actor.add_child(this._highlight); - - } - if (this._flash == null) { - this._flash = new St.Bin({ - width: 1, - height: 1, - opacity: 255, - reactive: false, - x: 0, - y: 0, - }); - this._flash.set_style(this._getHighlightStyle(1)); - let constraint = Clutter.BindConstraint.new(window_actor, Clutter.BindCoordinate.SIZE, 0); - this._flash.add_constraint(constraint); - window_actor.add_child(this._flash); - this._flash.ease({ - opacity: 0, - duration: 500, - mode: Clutter.AnimationMode.EASE_OUT_QUINT, - onComplete: () => { - this._pulse_highlight(); - } - }); - } - } - return Clutter.EVENT_PROPAGATE; - } - - addIcon() { - let app = this.switcher._tracker.get_window_app(this.metaWin); - let icon_size = this.switcher._settings.overlay_icon_size; - this._icon = app ? app.create_icon_texture(Math.min(icon_size, this.width, this.height) / this.scale) : null; - - if (this._icon == null) { - this._icon = new St.Icon({ - icon_name: 'applications-other', - }); - } - - let constraint = Clutter.BindConstraint.new(this, Clutter.BindCoordinate.ALL, 0); - this._icon.add_constraint(constraint); - - this.bind_property_full('opacity', - this._icon, 'opacity', - GObject.BindingFlags.SYNC_CREATE, - (bind, source) => { - /* So that the icon fades out 1) when the preview fades - out, such as in the timeline switcher, and - 2) when the icon is being removed, - but also ensure the icon only goes as high as the setting - opacity, we take the minimum of those three as our opacity. - Seems there might be a better way, but I'm not sure. - */ - return [true, Math.min(source, 255 * this.remove_icon_opacity, 255 * this.switcher._settings.overlay_icon_opacity)]; - }, - null); - this.bind_property('rotation_angle_y', this._icon, 'rotation_angle_y', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('pivot_point', this._icon, 'pivot_point', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('translation_x', this._icon, 'translation_x', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('scale_x', this._icon, 'scale_x', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('scale_y', this._icon, 'scale_y', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('scale_z', this._icon, 'scale_z', - GObject.BindingFlags.SYNC_CREATE); - this.switcher.previewActor.add_child(this._icon); - - if (this.switcher._settings.icon_has_shadow) { - this._icon.add_style_class_name("icon-dropshadow"); - } - - } - - removeIcon(animation_time) { - if (this._icon != null) { - let transition = Clutter.PropertyTransition.new('remove_icon_opacity'); - transition.duration = 1000.0 * animation_time; - this._icon.remove_icon_opacity_start = this._icon.opacity / 255.; - transition.set_from(this._icon.remove_icon_opacity_start); - transition.set_to(0); - transition.remove_on_complete = true; - transition.connect('new-frame', (timeline, msecs) => { - this._icon.opacity = 255 * this._icon.remove_icon_opacity_start * (1 - - timeline.get_progress());//(1 - msecs / transition.duration); - this._icon.queue_redraw(); - }) - transition.connect('completed', (timeline) => { - if (this._icon != null) { - this._icon.destroy() - this._icon = null; - } - }); - this.add_transition('remove_icon_opacity_transition', transition); - } - } - - vfunc_leave_event(crossingEvent) { - this.remove_highlight(); - this._entered = false; - if (this.switcher._settings.raise_mouse_over && !this.switcher._animatingClosed) this.switcher._updatePreviews(true, 0); - return Clutter.EVENT_PROPAGATE; - } - - /** - * Gets the pivot point relative to the preview. - * - * @param {Placement} placement - * @return {Graphene.Point} - */ - get_pivot_point_placement(placement) { - let xFraction = 0, - yFraction = 0; - - // Set xFraction - switch (placement) { - case Placement.TOP_LEFT: - case Placement.LEFT: - case Placement.BOTTOM_LEFT: - xFraction = 0; - break; - - case Placement.TOP: - case Placement.CENTER: - case Placement.BOTTOM: - xFraction = 0.5; - break; - - case Placement.TOP_RIGHT: - case Placement.RIGHT: - case Placement.BOTTOM_RIGHT: - xFraction = 1; - break; - - default: - throw new Error("Unknown placement given"); - } - - // Set yFraction - switch (placement) { - case Placement.TOP_LEFT: - case Placement.TOP: - case Placement.TOP_RIGHT: - yFraction = 0; - break; - - case Placement.LEFT: - case Placement.CENTER: - case Placement.RIGHT: - yFraction = 0.5; - break; - - case Placement.BOTTOM_LEFT: - case Placement.BOTTOM: - case Placement.BOTTOM_RIGHT: - yFraction = 1; - break; - - default: - throw new Error("Unknown placement given"); - } - return new Graphene.Point({ x: xFraction, y: yFraction }); - } - - /** - * Sets the pivot point placement, relative to the preview. - * - * @param {Placement} placement - * @return {void} - */ - set_pivot_point_placement(placement) { - let point = this.get_pivot_point_placement(placement); - this.set_pivot_point(point.x, point.y); - } -}); - -export function findUpperLeftFromCenter(sideSize, position) { - return position - sideSize / 2; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/schemas/gschemas.compiled deleted file mode 100755 index cdf0e3dd..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/schemas/org.gnome.shell.extensions.coverflowalttab.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/schemas/org.gnome.shell.extensions.coverflowalttab.gschema.xml deleted file mode 100755 index 34be12b5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/schemas/org.gnome.shell.extensions.coverflowalttab.gschema.xml +++ /dev/null @@ -1,228 +0,0 @@ - - - - - true - Hide the panel when showing coverflow - Whether to show or hide the panel when CoverflowAltTab is active. - - - false - Always show the switcher on the primary monitor - Show the switcher on the primary monitor instead of detecting the active monitor. - - - - 0.2 - The duration of coverflow animations in ms - Define the duration of the animations. - - - - 1 - Dim factor for background - Define dimming of the background. Bigger means darker. - - - - - - - "Bottom" - Position of icon and window title - Whether the icon and window title should be placed below or above the window preview. - - - - 0 - Set a vertical offset - Set a vertical offset. Positive values move the whole Coverflow up, negative down. - - - - - - - - "Classic" - Icon style - Whether the application icon should be displayed next to the title label or as an overlay. - - - - 1 - The opacity of the overlay icon - Define the opacity of the overlay icon. - - - - 128 - The icon size. - Size in pixels. - - - - - - - "Coverflow" - Switcher style - The switcher display style. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "ease-out-cubic" - Easing function used in animations - Use this easing function for animations. - - - - - - - - 'current' - Show windows from current workspace only - Whether to show all windows or windows from current workspace only. - - - false - Per monitor window switch - Switch between windows on current monitor (monitor with the mouse cursor) - - - false - Icon has shadow switch - Whether or not the icons have a drop shadow. - - - false - Randomize animation times switch - Whether or not to have each animation take a different, randomized time to complete. - - - - 0.5 - The maximum ratio of the preview dimensions with the monitor dimensions - Define the ratio of the preview to monitor sizes. - - - - 0.8 - In Coverflow Switcher, scales the previews as they spread out to the sides in - Define the scale factor successively applied each step away from the current preview. - - - true - Bind to 'switch-applications' keybinding - Whether or not to bind to the 'switch-applications' keybinding. - - - true - Bind to 'switch-windows' keybinding - Whether or not to bind to the 'switch-windows' keybinding. - - - false - Highlight window under mouse - Whether or not to draw some flare on the window under the mouse so you know. - - - true - Raise window under mouse - Whether or not to raise the window under the mouse above others. - - - - - - - - "Move Camera" - Method to correct off-center monitor perspective - Way to make off-center monitor switcher to look like centered. - - - 0.0 - - Amount to Desaturate the Background Application Switcher - 0 for no desaturation, 1 for total desaturation. - - - 0 - - Radius of Blur Applied to the Background Application Switcher - The bigger, the blurrier. - - - - - - - "Flip Stack" - How the windows cycle through the coverflow - - - false - The application-switcher keybinding action behaves the same as the window-switcher - - - true - Whether to Use a Tint Color on the Background Application Switcher - - - (0.,0.,0.) - - - - (0.,0.,0.) - - - - 0.0 - - Amount to Blend Tint Color - - - false - Use a "glitch effect" on the background application switcher - - - false - Swipe content instead of view - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/swipeTracker.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/swipeTracker.js deleted file mode 100755 index e55174d1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/swipeTracker.js +++ /dev/null @@ -1,786 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- -/* exported SwipeTracker */ - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import Mtk from 'gi://Mtk'; -import GObject from 'gi://GObject'; - -import * as Params from 'resource:///org/gnome/shell/misc/params.js'; - -// FIXME: ideally these values matches physical touchpad size. We can get the -// correct values for gnome-shell specifically, since mutter uses libinput -// directly, but GTK apps cannot get it, so use an arbitrary value so that -// it's consistent with apps. -const TOUCHPAD_BASE_HEIGHT = 300; -const TOUCHPAD_BASE_WIDTH = 400; - -const EVENT_HISTORY_THRESHOLD_MS = 150; - -const SCROLL_MULTIPLIER = 10; - -const MIN_ANIMATION_DURATION = 100; -const MAX_ANIMATION_DURATION = 400; -const VELOCITY_THRESHOLD_TOUCH = 0.3; -const VELOCITY_THRESHOLD_TOUCHPAD = 0.6; -const DECELERATION_TOUCH = 0.998; -const DECELERATION_TOUCHPAD = 0.997; -const VELOCITY_CURVE_THRESHOLD = 2; -const DECELERATION_PARABOLA_MULTIPLIER = 0.35; -const DRAG_THRESHOLD_DISTANCE = 16; - -// Derivative of easeOutCubic at t=0 -const DURATION_MULTIPLIER = 3; -const ANIMATION_BASE_VELOCITY = 0.002; -const EPSILON = 0.005; - -const GESTURE_FINGER_COUNT = 3; - -const State = { - NONE: 0, - SCROLLING: 1, -}; - -const TouchpadState = { - NONE: 0, - PENDING: 1, - HANDLING: 2, - IGNORED: 3, -}; - -const EventHistory = class { - constructor() { - this.reset(); - } - - reset() { - this._data = []; - } - - trim(time) { - const thresholdTime = time - EVENT_HISTORY_THRESHOLD_MS; - const index = this._data.findIndex(r => r.time >= thresholdTime); - - this._data.splice(0, index); - } - - append(time, delta) { - this.trim(time); - - this._data.push({ time, delta }); - } - - calculateVelocity() { - if (this._data.length < 2) - return 0; - - const firstTime = this._data[0].time; - const lastTime = this._data[this._data.length - 1].time; - - if (firstTime === lastTime) - return 0; - - const totalDelta = this._data.slice(1).map(a => a.delta).reduce((a, b) => a + b); - const period = lastTime - firstTime; - - return totalDelta / period; - } -}; - -const TouchpadSwipeGesture = GObject.registerClass({ - Properties: { - 'enabled': GObject.ParamSpec.boolean( - 'enabled', 'enabled', 'enabled', - GObject.ParamFlags.READWRITE, - true), - 'orientation': GObject.ParamSpec.enum( - 'orientation', 'orientation', 'orientation', - GObject.ParamFlags.READWRITE, - Clutter.Orientation, Clutter.Orientation.HORIZONTAL), - }, - Signals: { - 'begin': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] }, - 'update': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] }, - 'end': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE] }, - }, -}, class TouchpadSwipeGesture extends GObject.Object { - _init(allowedModes) { - super._init(); - this._allowedModes = allowedModes; - this._state = TouchpadState.NONE; - this._cumulativeX = 0; - this._cumulativeY = 0; - this._touchpadSettings = new Gio.Settings({ - schema_id: 'org.gnome.desktop.peripherals.touchpad', - }); - - global.stage.connectObject( - 'captured-event::touchpad', this._handleEvent.bind(this), this); - } - - _handleEvent(actor, event) { - if (event.type() !== Clutter.EventType.TOUCHPAD_SWIPE) - return Clutter.EVENT_PROPAGATE; - - if (event.get_gesture_phase() === Clutter.TouchpadGesturePhase.BEGIN) - this._state = TouchpadState.NONE; - - if (event.get_touchpad_gesture_finger_count() !== GESTURE_FINGER_COUNT) - return Clutter.EVENT_PROPAGATE; - - /* if ((this._allowedModes & Main.actionMode) === 0) - return Clutter.EVENT_PROPAGATE; */ - - if (!this.enabled) - return Clutter.EVENT_PROPAGATE; - - if (this._state === TouchpadState.IGNORED) - return Clutter.EVENT_PROPAGATE; - - let time = event.get_time(); - - const [x, y] = event.get_coords(); - const [dx, dy] = event.get_gesture_motion_delta_unaccelerated(); - - if (this._state === TouchpadState.NONE) { - if (dx === 0 && dy === 0) - return Clutter.EVENT_PROPAGATE; - - this._cumulativeX = 0; - this._cumulativeY = 0; - this._state = TouchpadState.PENDING; - } - - if (this._state === TouchpadState.PENDING) { - this._cumulativeX += dx; - this._cumulativeY += dy; - - const cdx = this._cumulativeX; - const cdy = this._cumulativeY; - const distance = Math.sqrt(cdx * cdx + cdy * cdy); - - if (distance >= DRAG_THRESHOLD_DISTANCE) { - const gestureOrientation = Math.abs(cdx) > Math.abs(cdy) - ? Clutter.Orientation.HORIZONTAL - : Clutter.Orientation.VERTICAL; - - this._cumulativeX = 0; - this._cumulativeY = 0; - - if (gestureOrientation === this.orientation) { - this._state = TouchpadState.HANDLING; - this.emit('begin', time, x, y); - } else { - this._state = TouchpadState.IGNORED; - return Clutter.EVENT_PROPAGATE; - } - } else { - return Clutter.EVENT_PROPAGATE; - } - } - - const vertical = this.orientation === Clutter.Orientation.VERTICAL; - let delta = vertical ? dy : dx; - const distance = vertical ? TOUCHPAD_BASE_HEIGHT : TOUCHPAD_BASE_WIDTH; - - switch (event.get_gesture_phase()) { - case Clutter.TouchpadGesturePhase.BEGIN: - case Clutter.TouchpadGesturePhase.UPDATE: - if (this._touchpadSettings.get_boolean('natural-scroll')) - delta = -delta; - - this.emit('update', time, delta, distance); - break; - - case Clutter.TouchpadGesturePhase.END: - case Clutter.TouchpadGesturePhase.CANCEL: - this.emit('end', time, distance); - this._state = TouchpadState.NONE; - break; - } - - return this._state === TouchpadState.HANDLING - ? Clutter.EVENT_STOP - : Clutter.EVENT_PROPAGATE; - } - - destroy() { - global.stage.disconnectObject(this); - } -}); - -const TouchSwipeGesture = GObject.registerClass({ - Properties: { - 'distance': GObject.ParamSpec.double( - 'distance', 'distance', 'distance', - GObject.ParamFlags.READWRITE, - 0, Infinity, 0), - 'orientation': GObject.ParamSpec.enum( - 'orientation', 'orientation', 'orientation', - GObject.ParamFlags.READWRITE, - Clutter.Orientation, Clutter.Orientation.HORIZONTAL), - }, - Signals: { - 'begin': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] }, - 'update': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] }, - 'end': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE] }, - 'cancel': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE] }, - }, -}, class TouchSwipeGesture extends Clutter.GestureAction { - _init(allowedModes, nTouchPoints, thresholdTriggerEdge) { - super._init(); - this.set_n_touch_points(nTouchPoints); - this.set_threshold_trigger_edge(thresholdTriggerEdge); - - this._allowedModes = allowedModes; - this._distance = global.screen_height; - this._lastPosition = 0; - } - - get distance() { - return this._distance; - } - - set distance(distance) { - if (this._distance === distance) - return; - - this._distance = distance; - this.notify('distance'); - } - - vfunc_gesture_prepare(actor) { - if (!super.vfunc_gesture_prepare(actor)) - return false; - - /* if ((this._allowedModes & Main.actionMode) === 0) - return false; */ - - let time = this.get_last_event(0).get_time(); - let [xPress, yPress] = this.get_press_coords(0); - let [x, y] = this.get_motion_coords(0); - const [xDelta, yDelta] = [x - xPress, y - yPress]; - const swipeOrientation = Math.abs(xDelta) > Math.abs(yDelta) - ? Clutter.Orientation.HORIZONTAL : Clutter.Orientation.VERTICAL; - - if (swipeOrientation !== this.orientation) - return false; - - this._lastPosition = - this.orientation === Clutter.Orientation.VERTICAL ? y : x; - - this.emit('begin', time, xPress, yPress); - return true; - } - - vfunc_gesture_progress(_actor) { - let [x, y] = this.get_motion_coords(0); - let pos = this.orientation === Clutter.Orientation.VERTICAL ? y : x; - - let delta = pos - this._lastPosition; - this._lastPosition = pos; - - let time = this.get_last_event(0).get_time(); - - this.emit('update', time, -delta, this._distance); - - return true; - } - - vfunc_gesture_end(_actor) { - let time = this.get_last_event(0).get_time(); - - this.emit('end', time, this._distance); - } - - vfunc_gesture_cancel(_actor) { - let time = Clutter.get_current_event_time(); - - this.emit('cancel', time, this._distance); - } -}); - -const ScrollGesture = GObject.registerClass({ - Properties: { - 'enabled': GObject.ParamSpec.boolean( - 'enabled', 'enabled', 'enabled', - GObject.ParamFlags.READWRITE, - true), - 'orientation': GObject.ParamSpec.enum( - 'orientation', 'orientation', 'orientation', - GObject.ParamFlags.READWRITE, - Clutter.Orientation, Clutter.Orientation.HORIZONTAL), - 'scroll-modifiers': GObject.ParamSpec.flags( - 'scroll-modifiers', 'scroll-modifiers', 'scroll-modifiers', - GObject.ParamFlags.READWRITE, - Clutter.ModifierType, 0), - }, - Signals: { - 'begin': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] }, - 'update': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] }, - 'end': { param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE] }, - }, -}, class ScrollGesture extends GObject.Object { - _init(actor, allowedModes, inverted=false) { - super._init(); - this._inverted = inverted; - this._allowedModes = allowedModes; - this._began = false; - this._enabled = true; - actor.connect('scroll-event', this._handleEvent.bind(this)); - } - - get enabled() { - return this._enabled; - } - - set enabled(enabled) { - if (this._enabled === enabled) - return; - - this._enabled = enabled; - this._began = false; - - this.notify('enabled'); - } - - canHandleEvent(event) { - if (event.type() !== Clutter.EventType.SCROLL) - return false; - - if (event.get_scroll_source() !== Clutter.ScrollSource.FINGER && - event.get_source_device().get_device_type() !== Clutter.InputDeviceType.TOUCHPAD_DEVICE) - return false; - - if (!this.enabled) - return false; - - if (!this._began && this.scrollModifiers !== 0 && - (event.get_state() & this.scrollModifiers) === 0) - return false; - - return true; - } - - _handleEvent(actor, event) { - if (!this.canHandleEvent(event)) - return Clutter.EVENT_PROPAGATE; - - if (event.get_scroll_direction() !== Clutter.ScrollDirection.SMOOTH) - return Clutter.EVENT_PROPAGATE; - - const vertical = this.orientation === Clutter.Orientation.VERTICAL; - const distance = vertical ? TOUCHPAD_BASE_HEIGHT : TOUCHPAD_BASE_WIDTH; - - let time = event.get_time(); - let [dx, dy] = event.get_scroll_delta(); - if (this._inverted) { - dx = -dx; dy = -dy; - } - - if (dx === 0 && dy === 0) { - this.emit('end', time, distance); - this._began = false; - return Clutter.EVENT_STOP; - } - - if (!this._began) { - let [x, y] = event.get_coords(); - this.emit('begin', time, x, y); - this._began = true; - } - - const delta = (vertical ? dy : dx) * SCROLL_MULTIPLIER; - - this.emit('update', time, delta, distance); - - return Clutter.EVENT_STOP; - } -}); - -// USAGE: -// -// To correctly implement the gesture, there must be handlers for the following -// signals: -// -// begin(tracker, monitor) -// The handler should check whether a deceleration animation is currently -// running. If it is, it should stop the animation (without resetting -// progress). Then it should call: -// tracker.confirmSwipe(distance, snapPoints, currentProgress, cancelProgress) -// If it's not called, the swipe would be ignored. -// The parameters are: -// * distance: the page size; -// * snapPoints: an (sorted with ascending order) array of snap points; -// * currentProgress: the current progress; -// * cancelprogress: a non-transient value that would be used if the gesture -// is cancelled. -// If no animation was running, currentProgress and cancelProgress should be -// same. The handler may set 'orientation' property here. -// -// update(tracker, progress) -// The handler should set the progress to the given value. -// -// end(tracker, duration, endProgress) -// The handler should animate the progress to endProgress. If endProgress is -// 0, it should do nothing after the animation, otherwise it should change the -// state, e.g. change the current page or switch workspace. -// NOTE: duration can be 0 in some cases, in this case it should finish -// instantly. - -/** A class for handling swipe gestures */ -export const MySwipeTracker = GObject.registerClass({ - Properties: { - 'enabled': GObject.ParamSpec.boolean( - 'enabled', 'enabled', 'enabled', - GObject.ParamFlags.READWRITE, - true), - 'orientation': GObject.ParamSpec.enum( - 'orientation', 'orientation', 'orientation', - GObject.ParamFlags.READWRITE, - Clutter.Orientation, Clutter.Orientation.HORIZONTAL), - 'distance': GObject.ParamSpec.double( - 'distance', 'distance', 'distance', - GObject.ParamFlags.READWRITE, - 0, Infinity, 0), - 'allow-long-swipes': GObject.ParamSpec.boolean( - 'allow-long-swipes', 'allow-long-swipes', 'allow-long-swipes', - GObject.ParamFlags.READWRITE, - false), - 'scroll-modifiers': GObject.ParamSpec.flags( - 'scroll-modifiers', 'scroll-modifiers', 'scroll-modifiers', - GObject.ParamFlags.READWRITE, - Clutter.ModifierType, 0), - }, - Signals: { - 'begin': { param_types: [GObject.TYPE_UINT] }, - 'update': { param_types: [GObject.TYPE_DOUBLE] }, - 'end': { param_types: [GObject.TYPE_UINT64, GObject.TYPE_DOUBLE] }, - }, -}, class MySwipeTracker extends GObject.Object { - _init(actor, orientation, allowedModes, params, inverted=false) { - super._init(); - params = Params.parse(params, { allowDrag: true, allowScroll: true }); - this.orientation = orientation; - this._inverted = inverted; - this._allowedModes = allowedModes; - this._enabled = true; - this._distance = global.screen_height; - this._history = new EventHistory(); - this._reset(); - - this._touchpadGesture = new TouchpadSwipeGesture(allowedModes); - this._touchpadGesture.connect('begin', this._beginGesture.bind(this)); - this._touchpadGesture.connect('update', this._updateGesture.bind(this)); - this._touchpadGesture.connect('end', this._endTouchpadGesture.bind(this)); - this.bind_property('enabled', this._touchpadGesture, 'enabled', 0); - this.bind_property('orientation', this._touchpadGesture, 'orientation', - GObject.BindingFlags.SYNC_CREATE); - - this._touchGesture = new TouchSwipeGesture(allowedModes, - GESTURE_FINGER_COUNT, - Clutter.GestureTriggerEdge.AFTER); - this._touchGesture.connect('begin', this._beginTouchSwipe.bind(this)); - this._touchGesture.connect('update', this._updateGesture.bind(this)); - this._touchGesture.connect('end', this._endTouchGesture.bind(this)); - this._touchGesture.connect('cancel', this._cancelTouchGesture.bind(this)); - this.bind_property('enabled', this._touchGesture, 'enabled', 0); - this.bind_property('orientation', this._touchGesture, 'orientation', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('distance', this._touchGesture, 'distance', 0); - global.stage.add_action_full('swipe', Clutter.EventPhase.CAPTURE, this._touchGesture); - - if (params.allowDrag) { - this._dragGesture = new TouchSwipeGesture(allowedModes, 1, - Clutter.GestureTriggerEdge.AFTER); - this._dragGesture.connect('begin', this._beginGesture.bind(this)); - this._dragGesture.connect('update', this._updateGesture.bind(this)); - this._dragGesture.connect('end', this._endTouchGesture.bind(this)); - this._dragGesture.connect('cancel', this._cancelTouchGesture.bind(this)); - this.bind_property('enabled', this._dragGesture, 'enabled', 0); - this.bind_property('orientation', this._dragGesture, 'orientation', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('distance', this._dragGesture, 'distance', 0); - actor.add_action_full('drag', Clutter.EventPhase.CAPTURE, this._dragGesture); - } else { - this._dragGesture = null; - } - - if (params.allowScroll) { - this._scrollGesture = new ScrollGesture(actor, allowedModes, this._inverted); - this._scrollGesture.connect('begin', this._beginGesture.bind(this)); - this._scrollGesture.connect('update', this._updateGesture.bind(this)); - this._scrollGesture.connect('end', this._endTouchpadGesture.bind(this)); - this.bind_property('enabled', this._scrollGesture, 'enabled', 0); - this.bind_property('orientation', this._scrollGesture, 'orientation', - GObject.BindingFlags.SYNC_CREATE); - this.bind_property('scroll-modifiers', - this._scrollGesture, 'scroll-modifiers', 0); - } else { - this._scrollGesture = null; - } - } - - /** - * canHandleScrollEvent: - * @param {Clutter.Event} scrollEvent: an event to check - * @returns {bool} whether the event can be handled by the tracker - * - * This function can be used to combine swipe gesture and mouse - * scrolling. - */ - canHandleScrollEvent(scrollEvent) { - if (!this.enabled || this._scrollGesture === null) { - return false; - } - - return this._scrollGesture.canHandleEvent(scrollEvent); - } - - get enabled() { - return this._enabled; - } - - set enabled(enabled) { - if (this._enabled === enabled) - return; - - this._enabled = enabled; - if (!enabled && this._state === State.SCROLLING) - this._interrupt(); - this.notify('enabled'); - } - - get distance() { - return this._distance; - } - - set distance(distance) { - if (this._distance === distance) - return; - - this._distance = distance; - this.notify('distance'); - } - - _reset() { - this._state = State.NONE; - - this._snapPoints = []; - this._initialProgress = 0; - this._cancelProgress = 0; - - this._prevOffset = 0; - this._progress = 0; - - this._cancelled = false; - - this._history.reset(); - } - - _interrupt() { - this.emit('end', 0, this._cancelProgress); - this._reset(); - } - - _beginTouchSwipe(gesture, time, x, y) { - if (this._dragGesture) - this._dragGesture.cancel(); - - this._beginGesture(gesture, time, x, y); - } - - _beginGesture(gesture, time, x, y) { - if (this._state === State.SCROLLING) - return; - - this._history.append(time, 0); - - let rect = new Mtk.Rectangle({ x, y, width: 1, height: 1 }); - let monitor = global.display.get_monitor_index_for_rect(rect); - - this.emit('begin', monitor); - } - - _findClosestPoint(pos) { - const distances = this._snapPoints.map(x => Math.abs(x - pos)); - const min = Math.min(...distances); - return distances.indexOf(min); - } - - _findNextPoint(pos) { - return this._snapPoints.findIndex(p => p >= pos); - } - - _findPreviousPoint(pos) { - const reversedIndex = this._snapPoints.slice().reverse().findIndex(p => p <= pos); - return this._snapPoints.length - 1 - reversedIndex; - } - - _findPointForProjection(pos, velocity) { - const initial = this._findClosestPoint(this._initialProgress); - const prev = this._findPreviousPoint(pos); - const next = this._findNextPoint(pos); - - if ((velocity > 0 ? prev : next) === initial) - return velocity > 0 ? next : prev; - - return this._findClosestPoint(pos); - } - - _getBounds(pos) { - if (this.allowLongSwipes) - return [this._snapPoints[0], this._snapPoints[this._snapPoints.length - 1]]; - - const closest = this._findClosestPoint(pos); - - let prev, next; - if (Math.abs(this._snapPoints[closest] - pos) < EPSILON) { - prev = next = closest; - } else { - prev = this._findPreviousPoint(pos); - next = this._findNextPoint(pos); - } - - const lowerIndex = Math.max(prev - 1, 0); - const upperIndex = Math.min(next + 1, this._snapPoints.length - 1); - - return [this._snapPoints[lowerIndex], this._snapPoints[upperIndex]]; - } - - _updateGesture(gesture, time, delta, distance) { - if (this._state !== State.SCROLLING) - return; - - if (!this.enabled) { - this._interrupt(); - return; - } - - if (this.orientation === Clutter.Orientation.HORIZONTAL && - Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) - delta = -delta; - - this._progress += delta / distance; - this._history.append(time, delta); - - this._progress = Math.clamp(this._progress, ...this._getBounds(this._initialProgress)); - - this.emit('update', this._progress); - } - - _getEndProgress(velocity, distance, isTouchpad) { - if (this._cancelled) - return this._cancelProgress; - - const threshold = isTouchpad ? VELOCITY_THRESHOLD_TOUCHPAD : VELOCITY_THRESHOLD_TOUCH; - - if (Math.abs(velocity) < threshold) - return this._snapPoints[this._findClosestPoint(this._progress)]; - - const decel = isTouchpad ? DECELERATION_TOUCHPAD : DECELERATION_TOUCH; - const slope = decel / (1.0 - decel) / 1000.0; - - let pos; - if (Math.abs(velocity) > VELOCITY_CURVE_THRESHOLD) { - const c = slope / 2 / DECELERATION_PARABOLA_MULTIPLIER; - const x = Math.abs(velocity) - VELOCITY_CURVE_THRESHOLD + c; - - pos = slope * VELOCITY_CURVE_THRESHOLD + - DECELERATION_PARABOLA_MULTIPLIER * x * x - - DECELERATION_PARABOLA_MULTIPLIER * c * c; - } else { - pos = Math.abs(velocity) * slope; - } - - pos = pos * Math.sign(velocity) + this._progress; - pos = Math.clamp(pos, ...this._getBounds(this._initialProgress)); - - const index = this._findPointForProjection(pos, velocity); - - return this._snapPoints[index]; - } - - _endTouchGesture(_gesture, time, distance) { - this._endGesture(time, distance, false); - } - - _endTouchpadGesture(_gesture, time, distance) { - this._endGesture(time, distance, true); - } - - _endGesture(time, distance, isTouchpad) { - if (this._state !== State.SCROLLING) - return; - - /* if ((this._allowedModes & Main.actionMode) === 0 || !this.enabled) { - this._interrupt(); - return; - } */ - - this._history.trim(time); - - let velocity = this._history.calculateVelocity(); - const endProgress = this._getEndProgress(velocity, distance, isTouchpad); - - velocity /= distance; - - if ((endProgress - this._progress) * velocity <= 0) - velocity = ANIMATION_BASE_VELOCITY; - - const nPoints = Math.max(1, Math.ceil(Math.abs(this._progress - endProgress))); - const maxDuration = MAX_ANIMATION_DURATION * Math.log2(1 + nPoints); - - let duration = Math.abs((this._progress - endProgress) / velocity * DURATION_MULTIPLIER); - if (duration > 0) - duration = Math.clamp(duration, MIN_ANIMATION_DURATION, maxDuration); - - this._reset(); - this.emit('end', duration, endProgress); - } - - _cancelTouchGesture(_gesture, time, distance) { - if (this._state !== State.SCROLLING) - return; - - this._cancelled = true; - this._endGesture(time, distance, false); - } - - /** - * confirmSwipe: - * @param {number} distance: swipe distance in pixels - * @param {number[]} snapPoints: - * An array of snap points, sorted in ascending order - * @param {number} currentProgress: initial progress value - * @param {number} cancelProgress: the value to be used on cancelling - * - * Confirms a swipe. User has to call this in 'begin' signal handler, - * otherwise the swipe wouldn't start. If there's an animation running, - * it should be stopped first. - * - * @cancel_progress must always be a snap point, or a value matching - * some other non-transient state. - */ - confirmSwipe(distance, snapPoints, currentProgress, cancelProgress) { - this.distance = distance; - this._snapPoints = snapPoints; - this._initialProgress = currentProgress; - this._progress = currentProgress; - this._cancelProgress = cancelProgress; - - this._state = State.SCROLLING; - } - - destroy() { - if (this._touchpadGesture) { - this._touchpadGesture.destroy(); - delete this._touchpadGesture; - } - - if (this._touchGesture) { - global.stage.remove_action(this._touchGesture); - delete this._touchGesture; - } - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/switcher.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/switcher.js deleted file mode 100755 index 7b1227ea..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/switcher.js +++ /dev/null @@ -1,1227 +0,0 @@ -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* CoverflowAltTab::Switcher: - * - * The implementation of the switcher UI. Handles keyboard events. - */ -import Clutter from 'gi://Clutter'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; -import Meta from 'gi://Meta'; -import Pango from 'gi://Pango'; -import GLib from 'gi://GLib'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import {ColorEffect} from './effects/color_effect.js'; -import {GlitchEffect} from './effects/glitch_effect.js'; -import {Placement, Direction} from './preview.js'; -import {MySwipeTracker} from './swipeTracker.js'; - -import {__ABSTRACT_METHOD__} from './lib.js'; - -const INITIAL_DELAY_TIMEOUT = 150; -const ICON_SIZE = 64; -const ICON_TITLE_SPACING = 10; - -let CloseReason = class CloseReason {} -CloseReason.ACTIVATE_SELECTED = 1; -CloseReason.NO_ACTIVATION = 2; - -export class Switcher { - constructor(windows, mask, currentIndex, manager, activeMonitor=null, isAppSwitcher=false, parent=null, x_in, y_in, width_in, height_in) { - this._manager = manager; - this._settings = manager.platform.getSettings(); - this._windows = [...windows]; - this._modifierMask = null; - this._currentIndex = currentIndex; - this._haveModal = false; - this._tracker = manager.platform.getWindowTracker(); - this._windowManager = global.window_manager; - this._previews = []; - this._allPreviews = []; - this._numPreviewsComplete = 0; - this._isAppSwitcher = isAppSwitcher; - this._appWindowsMap = new Map(); - this._x = x_in; - this._y = y_in; - this._width = width_in; - this._height = height_in; - this._parent = parent; - this._subSwitchers = new Map(); - this._backgroundColor = null; - this._windowTitles = []; - this._windowIconBoxes = []; - this._toSubSwitcher = null; - this._fromSubSwitcher = null; - this._grab = null; - this._animatingClosed = false; - - if (activeMonitor !== null) - this._activeMonitor = activeMonitor; - - let monitor = this._updateActiveMonitor(); - - this._dcid = this._windowManager.connect('destroy', this._windowDestroyed.bind(this)); - this._mcid = this._windowManager.connect('map', this._activateSelected.bind(this)); - manager.platform.switcher = this; - if (this._parent === null) manager.platform.initBackground(); - - // create a container for all our widgets - let widgetClass = manager.platform.getWidgetClass(); - this.actor = new widgetClass({ visible: true, reactive: true, }); - this.actor.hide(); - this.previewActor = new widgetClass({ visible: true, reactive: true}); - this.actor.add_child(this.previewActor); - Main.uiGroup.add_child(this.actor); - - if (this._parent == null) { - this._grabModal(); - } - - if (this._parent === null) { - this.actor.set_size(monitor.width, monitor.height); - this.actor.set_position(monitor.x, monitor.y); - } else { - this.actor.set_size(this._width, this._height); - this.actor.set_position(this._x, this._y); - } - - this.gestureInProgress = false; - - const swipeTracker = new MySwipeTracker(this.actor, - Clutter.Orientation.HORIZONTAL, - 0, - { allowDrag: true, allowScroll: true }, - this._settings.invert_swipes); - swipeTracker.allowLongSwipes = true; - swipeTracker.connect('begin', this._gestureBegin.bind(this)); - swipeTracker.connect('update', this._gestureUpdate.bind(this)); - swipeTracker.connect('end', this._gestureEnd.bind(this)); - this._swipeTracker = swipeTracker; - - this._modifierMask = manager.platform.getPrimaryModifier(mask); - - if (this._isAppSwitcher) { - // Find all the apps and associated windows - for (let metaWin of this._windows) { - let app = this._tracker.get_window_app(metaWin); - if (this._appWindowsMap.has(app)) { - this._appWindowsMap.get(app).push(metaWin); - } else { - this._appWindowsMap.set(app, [metaWin]); - } - } - /* If only one app, then just switch between the windows of - that app. */ - if (Array.from(this._appWindowsMap.keys()).length === 1) { - this._isAppSwitcher = false; - } else { - // For each app, display the first window only - this._windows = []; - for (let app of this._appWindowsMap.keys()) { - let window = this._appWindowsMap.get(app)[0] - this._windows.push(window); - if (this._appWindowsMap.get(app).length > 1) { - let switcher_class = this._manager.platform.getSettings().switcher_class; - this._subSwitchers.set(window, new switcher_class(this._appWindowsMap.get(app), this._modifierMask, 0, this._manager, this._activeMonitor, false, this, - this.actor.x, this.actor.y, this.actor.width, this.actor.height)); - } - } - } - } - - let [x, y, mods] = global.get_pointer(); - if (!(mods & this._modifierMask)) { - // There's a race condition; if the user released Alt before - // we got the grab, then we won't be notified. (See - // https://bugzilla.gnome.org/show_bug.cgi?id=596695 for - // details) So we check now. (Have to do this after updating - // selection.) - this._activateSelected(); - return; - } - - if (this._parent == null) this._initialDelayTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, INITIAL_DELAY_TIMEOUT, this.show.bind(this)); - } - - show() { - let monitor = this._updateActiveMonitor(); - - // create previews - this._createPreviews(); - for (let i = 0; i < this._windows.length; i++) { - this._getWindowTitle(i); - } - - for (let preview of this._allPreviews) { - preview.set_reactive(false); - if (this._parent === null && this._settings.icon_style == "Attached" && this._previews.includes(preview)) { - preview.addIcon(); - } - preview.connect('button-press-event', this._previewButtonPressEvent.bind(this, preview)); - } - - // hide windows and showcd Coverflow actors - if (this._parent === null) global.window_group.hide(); - - if (this._parent === null) this.actor.show(); - if (this._parent !== null) { - this.previewActor.set_scale(0, 0); - this.previewActor.set_scale_z(0); - - this._updateWindowTitle(); - this._updatePreviews(false); - - } - this._enablePerspectiveCorrection(); - this._initialDelayTimeoutId = 0; - for (let preview of this._allPreviews) { - if (!this._previews.includes(preview)) { - if (this._parent !== null) { - preview.opacity = 0; - preview.x = 0; - preview.y = 0; - preview.scale_x = 0; - preview.scale_y = 0; - preview.scale_z = 0; - } - } - } - if (this._parent == null) { - for (let switcher of this._subSwitchers.values()) { - switcher.show(); - } - this._next(); - } - this._getSwitcherBackgroundColor(); - - } - - _gestureBegin(tracker) { - const baseDistance = 400; - const progress = this._currentIndex; - const points = []; - for (let i = 0; i < this._previews.length; i++) { - points.push(i); - } - - const cancelProgress = Math.round(progress); - tracker.confirmSwipe(baseDistance, points, progress, cancelProgress); - this.gestureInProgress = true; - } - - _gestureUpdate(tracker, progress) { - if (this._currentIndex <= Math.round(this._currentIndex) && Math.round(this._currentIndex) < progress) { - this._showSubswitcher(Direction.TO_RIGHT); - } else if (this._currentIndex >= Math.round(this._currentIndex) && Math.round(this._currentIndex) > progress) { - this._showSubswitcher(Direction.TO_LEFT); - } - this._setCurrentIndex(progress); - - this._updateSubSwitcher(); - this._updateWindowTitle(); - this._updatePreviews(false); - } - - _gestureEnd(tracker, duration, endProgress) { - this.gestureInProgress = false; - this._setCurrentIndex(endProgress); - if (endProgress != this._toIndex) { - if (this._direction == Direction.TO_RIGHT) { - this._showSubswitcher(Direction.TO_LEFT); - } else { - this._showSubswitcher(Direction.TO_RIGHT); - } - } else { - this._showSubswitcher(this._direction); - } - this._updateWindowTitle(); - this._updatePreviews(false); - } - - _ungrabModal() { - if (this._haveModal) { - this.actor.disconnect(this._key_press_handler_id); - this.actor.disconnect(this._key_release_handler_id); - this.actor.disconnect(this._scroll_handler_id); - Main.popModal(this._grab); - this._haveModal = false; - } - } - - _grabModal() { - if (this._haveModal) return; - this._key_press_handler_id = this.actor.connect('key-press-event', this._keyPressEvent.bind(this)); - this._key_release_handler_id = this.actor.connect('key-release-event', this._keyReleaseEvent.bind(this)); - this._scroll_handler_id = this.actor.connect('scroll-event', this._scrollEvent.bind(this)); - this._grab = Main.pushModal(this.actor) - if (!this._grab) { - this._activateSelected(); - return; - } - this._haveModal = true; - } - - _addBackgroundEffects() { - for (let preview of this._previews) { - if (this._settings.use_glitch_effect) { - if (preview.get_effect('glitch-effect') === null) { - let glitchEffect = new GlitchEffect({}); - preview.add_effect_with_name('glitch-effect', glitchEffect); - } - preview.get_effect('glitch-effect').set_enabled(true); - preview._effectCounts['glitch'] += 1; - } - if (this._settings.use_tint) { - let c = this._settings.tint_color; - let b = this._settings.tint_blend; - preview.addEffect(ColorEffect, { color: [c[0], c[1], c[2], 0] }, 'tint', 'blend', 0.0, b, this._settings.animation_time); - } - - preview.addEffect(Clutter.DesaturateEffect, { factor: 0.0 }, 'desaturate', 'factor', 0.0, this._settings.desaturate_factor, this._settings.animation_time); - preview.addEffect(Shell.BlurEffect, { radius: 0.0 }, 'blur', 'raduis', 0.0, this._settings.blur_radius, this._settings.animation_time); - } - } - - _removeBackgroundEffects() { - if (this._previews !== null) { - for (let preview of this._previews) { - preview.removeEffect('blur', 'radius', 0.0, this._settings.animation_time); - preview.removeEffect('desaturate', 'factor', 0.0, this._settings.animation_time); - preview.removeEffect('tint', 'blend', 0.0, this._settings.animation_time); - if (preview._effectCounts['glitch'] > 0) { - preview._effectCounts['glitch'] -= 1; - if (preview._effectCounts['glitch'] == 0) { - preview.get_effect('glitch-effect').set_enabled(false); - } - } - } - } - } - - - - _stopClosing() { - this._animatingClosed = false; - for (let preview of this._allPreviews) { - if (!this._previews.includes(preview)) { - if (this._parent === null) { - let monitor = Main.layoutManager.monitors[preview.metaWin.get_monitor()]; - preview.set_pivot_point_placement(Placement.TOP_LEFT); - this._manager.platform.tween(preview, { - x: monitor.x - this.actor.x, - y: monitor.y - this.actor.y, - scale_x: 0, - scale_y: 0, - scale_z: 0, - opacity: 0, - time: this._getRandomTime(), - transition: 'easeInOutQuint', - }); - } else { - preview.opacity = 0; - preview.x = 0; - preview.y = 0; - preview.scale_x = 0; - preview.scale_y = 0; - preview.scale_z = 0; - } - } - } - } - - _createPreviews() { __ABSTRACT_METHOD__(this, this._createPreviews) } - _updatePreviews() { __ABSTRACT_METHOD__(this, this._updatePreviews) } - - _previewNext() { __ABSTRACT_METHOD__(this, this._previewNext) } - _previewPrevious() { __ABSTRACT_METHOD__(this, this._previewPrevious) } - - _showSubswitcher(direction) { - if (this._isAppSwitcher) { - this._direction = direction; - - let from_index = Math.round(this._currentIndex); - let to_index = Math.round(this._currentIndex + this._windows.length + (direction == Direction.TO_RIGHT ? 1 : -1)) % this._windows.length; - if (!this.gestureInProgress) { - to_index = this._currentIndex; - from_index = (this._currentIndex + this._windows.length + (direction == Direction.TO_RIGHT ? - 1 : 1)) % this._windows.length; - } - - this._fromIndex = from_index; - this._toIndex = to_index; - - this._fromSubSwitcher = this._numberOfWindows(from_index) > 1 ? this._subSwitchers.get(this._windows[from_index]) : null; - this._toSubSwitcher = this._numberOfWindows(to_index) > 1 ? this._subSwitchers.get(this._windows[to_index]) : null; - - if (this._toSubSwitcher != null) { - this._toSubSwitcher.actor.show(); - this._addBackgroundEffects(); - let current_index = direction == Direction.TO_RIGHT ? 0 : this._toSubSwitcher._windows.length - 1; - this._toSubSwitcher._setCurrentIndex(current_index); - this._toSubSwitcher._updateWindowTitle(); - this._toSubSwitcher._updatePreviews(false); - if (!this.gestureInProgress) { - this._toSubSwitcher._grabModal(); - } - } else { - this._removeBackgroundEffects(); - } - if (this._fromSubSwitcher != null) { - this._fromSubSwitcher._ungrabModal(); - this._removeBackgroundEffects(); - } - - this._updateSubSwitcher(); - } - } - - _getWindowsAtIndex(index) { - return this._appWindowsMap.get(this._tracker.get_window_app(this._windows[index])); - } - - _numberOfWindows(index) { - return this._getWindowsAtIndex(index).length; - } - - _updateSubSwitcher() { - if (this._isAppSwitcher) { - let scale = 1, x = 0; - let progress = 1; - let to_index = this._toIndex; - let from_index = this._fromIndex; - progress = (this._currentIndex - from_index) / (to_index - from_index); - let is_appswitcher_at_to_index = this._numberOfWindows(to_index) > 1; - let to_scale = is_appswitcher_at_to_index ? 0.25 : 1; - let is_appswitcher_at_from_index = this._numberOfWindows(from_index) > 1; - let from_scale = is_appswitcher_at_from_index ? 0.25 : 1; - scale = from_scale + progress * (to_scale - from_scale); - let from_x = is_appswitcher_at_from_index ? 0.375 * this.actor.width : 0; - let to_x = is_appswitcher_at_to_index ? 0.375 * this.actor.width : 0; - x = from_x + progress * (to_x - from_x); - - this._manager.platform.tween(this.previewActor, { - scale_x: scale, - scale_y: scale, - scale_z: scale, - opacity: 255, - x: x, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - }); - for (let switcher of this._subSwitchers.values()) { - if (switcher !== this._toSubSwitcher && switcher !== this._fromSubSwitcher) { - this._manager.platform.tween(switcher.previewActor, { - scale_x: 0, - scale_y: 0, - scale_z: 0, - opacity: 0, - time: this._settings.animation_time, - transition: 'easeInOutQuint', - }); - } - } - if (this._toSubSwitcher !== null && !this._toSubSwitcher._animatingClosed) { - this._manager.platform.tween(this._toSubSwitcher.previewActor, { - scale_x: this.gestureInProgress ? progress : 1, - scale_y: this.gestureInProgress ? progress : 1, - scale_z: this.gestureInProgress ? progress : 1, - opacity: this.gestureInProgress ? 255 * progress : 255, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - }); - } - if (this._fromSubSwitcher !== null && !this._fromSubSwitcher._animatingClosed) { - this._manager.platform.tween(this._fromSubSwitcher.previewActor, { - scale_x: this.gestureInProgress ? 1-progress : 0, - scale_y: this.gestureInProgress ? 1-progress : 0, - scale_z: this.gestureInProgress ? 1-progress : 0, - opacity: this.gestureInProgress ? 255 * (1 - progress) : 0, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - onComplete: () => { - if (!this.gestureInProgress) this._fromSubSwitcher.actor.hide(); - }, - }); - } - } - } - - _setCurrentIndex(value) { - this._currentIndex = value; - } - - _next() { - if (this._parent === null) this._manager.platform.dimBackground(); - this._stopClosing(); - if (this._windows.length <= 1) { - this._setCurrentIndex(0); - this._updatePreviews(false, 1); - } else { - this.actor.set_reactive(false); - if (this._parent && this._currentIndex == this._previews.length - 1) { - this._parent._next(); - } else { - this._previewNext(); - } - this._showSubswitcher(Direction.TO_RIGHT); - - this.actor.set_reactive(true); - } - this._updateWindowTitle(); - } - - _previous() { - if (this._parent === null) this._manager.platform.dimBackground(); - this._stopClosing(); - if (this._windows.length <= 1) { - this._setCurrentIndex(0); - this._updatePreviews(false, -1); - } else { - this.actor.set_reactive(false); - if (this._parent && this._currentIndex == 0) { - this._parent._previous(); - } else { - this._previewPrevious(); - } - this._showSubswitcher(Direction.TO_LEFT); - this.actor.set_reactive(true); - } - this._updateWindowTitle(); - } - - _getSwitcherBackgroundColor() { - if (this._backgroundColor === null) { - let widgetClass = this._manager.platform.getWidgetClass(); - let parent = new widgetClass({ visible: false, reactive: false, style_class: 'switcher-list'}); - let actor = new widgetClass({ visible: false, reactive: false, style_class: 'item-box' }); - parent.add_child(actor); - actor.add_style_pseudo_class('selected'); - Main.uiGroup.add_child(parent); - this._backgroundColor = actor.get_theme_node().get_background_color(); - Main.uiGroup.remove_child(parent); - parent = null; - let color = new GLib.Variant("(ddd)", [this._backgroundColor.red/255, this._backgroundColor.green/255, this._backgroundColor.blue/255]); - this._manager.platform._extensionSettings.set_value("switcher-background-color", color); - } - return this._backgroundColor; - } - - _updateActiveMonitor() { - // Always return the original monitor, otherwise, previews ease to the - // wrong monitor on destroy if you move the mouse to a different monitor. - if (!this._activeMonitor) { - if (!this._settings.enforce_primary_monitor) - this._activeMonitor = Main.layoutManager.currentMonitor; - else - this._activeMonitor = Main.layoutManager.primaryMonitor; - } - this.num_monitors = global.display.get_n_monitors(); - this.monitors_ltr = []; - for (let m of Main.layoutManager.monitors) { - this.monitors_ltr.push(m); - } - - this.monitors_ltr.sort(function compareFn(A, B) { - return A.x - B.x; - }); - - this.monitor_number = this._activeMonitor.index; - return this._activeMonitor; - } - - _raiseIcons() { - for (let i = 0; i < this._windows.length; i++) { - this.previewActor.set_child_above_sibling(this._windowTitles[i], null); - this.previewActor.set_child_above_sibling(this._windowIconBoxes[i], null); - } - - } - - _getWindowTitle(index) { - let overlay_icon_size = this._settings.overlay_icon_size; - let window_title = new St.Label({ - style_class: 'switcher-list', - text: this._windows[index].get_title(), - opacity: 0 - }); - this.previewActor.add_child(window_title); - let app_icon_size; - let label_offset; - if (this._settings.icon_style == "Classic") { - app_icon_size = this._settings.text_scaling_factor * ICON_SIZE ; - label_offset = this._settings.text_scaling_factor * (ICON_SIZE + ICON_TITLE_SPACING); - } else { - app_icon_size = this._settings.text_scaling_factor * overlay_icon_size; - label_offset = 0; - } - // ellipsize if title is too long - let font_size = 14 * this._settings.text_scaling_factor; - window_title.set_style("max-width:" + (this.actor.width - 200) + "px;font-size: " + font_size + "px;font-weight: bold; padding: " + font_size + "px;"); - window_title.clutter_text.ellipsize = Pango.EllipsizeMode.END; - - let cx = Math.round((this.actor.width + label_offset) / 2); - let cy = Math.round(this.actor.height * this._settings.title_position / 8 + this._settings.offset); - - window_title.x = cx - Math.round(window_title.get_width()/2); - window_title.y = cy - Math.round(window_title.get_height()/2); - this._windowTitles[index] = window_title; - - let app = this._tracker.get_window_app(this._windows[index]); - let icon = app ? app.create_icon_texture(app_icon_size) : null; - - if (!icon) { - icon = new St.Icon({ - icon_name: 'applications-other', - icon_size: app_icon_size - }); - } - - if (this._settings.icon_has_shadow) { - icon.add_style_class_name("icon-dropshadow"); - } - let application_icon_box; - if (this._settings.icon_style == "Classic") { - application_icon_box = new St.Bin({ - style_class: 'window-iconbox', - opacity: 0, - width: app_icon_size, - height: app_icon_size, - x: Math.round(this._windowTitles[index].x - app_icon_size - ICON_TITLE_SPACING), - y: Math.round(cy - app_icon_size/2) - }); - } else { - application_icon_box = new St.Bin({ - style_class: 'window-iconbox', - width: app_icon_size * 1.25, - height: app_icon_size * 1.25, - opacity: 0, - x: (this.actor.width - app_icon_size * 1.25) / 2, - y: (this.actor.height - app_icon_size * 1.25) / 2 + this._settings.offset, - }); - } - - application_icon_box.set_child(icon); - this.previewActor.add_child(application_icon_box); - this._windowIconBoxes[index] = application_icon_box; - } - - _updateWindowTitle() { - let idx_low = Math.floor(this._currentIndex); - let idx_high = Math.ceil(this._currentIndex); - - if (idx_low == idx_high) { - for (let window_title of this._windowTitles) { - this._manager.platform.tween(window_title, { - opacity: 0, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - }); - } - - let window_title = this._windowTitles[idx_low]; - this._manager.platform.tween(window_title, { - opacity: 255, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - }); - - for (let icon_box of this._windowIconBoxes) { - this._manager.platform.tween(icon_box, { - opacity: 0, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - }); - } - let alpha = 1; - if (this._settings.icon_style === "Attached") { - alpha = 0; - } else if (this._settings.icon_style === "Overlay") { - alpha = this._settings.overlay_icon_opacity; - } - - if ((this._parent == null && !this._isAppSwitcher) || (!this._settings.attach_overlay_icons && this._parent == null)) { - let icon_box = this._windowIconBoxes[idx_low]; - this._manager.platform.tween(icon_box, { - opacity: alpha * 255, - time: this.gestureInProgress ? 0 : this._settings.animation_time, - transition: 'easeInOutQuint', - }); - } - } else { - - let window_title_low = this._windowTitles[idx_low]; - let window_title_high = this._windowTitles[idx_high]; - - let progress = this._currentIndex - idx_low; - window_title_low.opacity = 255 * (1 - progress); - window_title_high.opacity = 255 * progress; - - let icon_box_low = this._windowIconBoxes[idx_low]; - let icon_box_high = this._windowIconBoxes[idx_high]; - - let alpha = 1; - if (this._settings.icon_style === "Attached") { - alpha = 0; - } else if (this._settings.icon_style === "Overlay") { - alpha = this._settings.overlay_icon_opacity; - } - - icon_box_low.opacity = alpha * 255 * (1 - progress); - icon_box_high.opacity = alpha * 255 * progress; - - } - } - - _keyPressEvent(actor, event) { - switch(event.get_key_symbol()) { - - case Clutter.KEY_Escape: - case Clutter.Escape: - // Esc -> close CoverFlow - this._activateSelected(); - return true; - - case Clutter.KEY_q: - case Clutter.KEY_Q: - case Clutter.KEY_F4: - case Clutter.q: - case Clutter.Q: - case Clutter.F4: - // Q -> Close window - this._manager.removeSelectedWindow(this._windows[this._currentIndex]); - return true; - - case Clutter.KEY_Down: - case Clutter.Down: - this._showSubswitcher(Direction.TO_RIGHT); - return true; - - case Clutter.KEY_Right: - case Clutter.Right: - // Right/Down -> navigate to next preview - this._next(); - return true; - - case Clutter.KEY_Left: - case Clutter.Left: - // Left/Up -> navigate to previous preview - this._previous(); - return true; - - case Clutter.KEY_d: - case Clutter.KEY_D: - case Clutter.d: - case Clutter.D: - // D -> Show desktop - this._showDesktop(); - return true; - } - // default alt-tab - let event_state = event.get_state(); - let action = global.display.get_keybinding_action(event.get_key_code(), event_state); - switch(action) { - case Meta.KeyBindingAction.SWITCH_APPLICATIONS: - case Meta.KeyBindingAction.SWITCH_GROUP: - case Meta.KeyBindingAction.SWITCH_WINDOWS: - - // shift -> backwards - if (event_state & Clutter.ModifierType.SHIFT_MASK) { - this._previous(); - } else { - this._next(); - } - - return true; - case Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD: - case Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD: - case Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD: - this._previous(); - return true; - } - - return true; - } - - _keyReleaseEvent(actor, event) { - let [x, y, mods] = global.get_pointer(); - let state = mods & this._modifierMask; - if (state == 0 && !this._animatingClosed) { - if (this._initialDelayTimeoutId !== 0) - this._setCurrentIndex((this._currentIndex + 1) % this._windows.length); - this._activateSelected(); - } - - return true; - } - - // allow navigating by mouse-wheel scrolling - _scrollEvent(actor, event) { - if (this._swipeTracker.canHandleScrollEvent(event)) - return Clutter.EVENT_PROPAGATE; - - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.SMOOTH: - let [dx, dy] = event.get_scroll_delta(); - if (dy > 0 || dx > 0) { - this._next(); - return true; - } else { - this._previous(); - return true; - } - break; - case Clutter.ScrollDirection.LEFT: - case Clutter.ScrollDirection.UP: - this._previous(); - break; - - case Clutter.ScrollDirection.RIGHT: - case Clutter.ScrollDirection.DOWN: - this._next(); - break; - } - - return true; - } - - _windowDestroyed(wm, actor) { - this._removeDestroyedWindow(actor.meta_window); - } - - _checkDestroyed(window) { - this._removeDestroyedWindow(window); - } - - _removeDestroyedWindow(window) { - for (let i in this._windows) { - if (window == this._windows[i]) { - if (this._windows.length === 1) - this.destroy(CloseReason.ACTIVATE_SELECTED); - else { - this._windows.splice(i, 1); - this._previews[i].destroy(); - this._previews.splice(i, 1); - this._setCurrentIndex((i < this._currentIndex) ? this._currentIndex - 1 : - this._currentIndex % this._windows.length); - this._updatePreviews(false, 0); - this._updateWindowTitle(); - } - return; - } - } - } - - _previewButtonPressEvent(preview) { - for (let [i, p] of this._previews.entries()) { - if (preview == p) { - this._setCurrentIndex(i); - this._activateSelected(true); - break; - } - } - } - - _activateSelected(reset_current_window_title) { - let preview = this._previews[this._currentIndex]; - if (preview) { - preview.remove_highlight(); - } - let win = this._windows[this._currentIndex]; - if (win) { - this._manager.activateSelectedWindow(win); - if (reset_current_window_title) this._updateWindowTitle(); - } - if (this._parent) { - this._parent.animateClosed(CloseReason.NO_ACTIVATION); - } - this.animateClosed(CloseReason.ACTIVATE_SELECTED); - } - - _showDesktop() { - for (let window of this._windows) { - if (!window.minimized) { - window.minimize(); - } - } - this.animateClosed(CloseReason.ACTIVATE_SELECTED); - } - - _getRandomArbitrary(min, max) { - return Math.random() * (max - min) + min; - } - - _getRandomTime() { - return this._settings.animation_time * (this._settings.randomize_animation_times ? this._getRandomArbitrary(0.0001, 1) : 1); - } - - _hide(reason) { - this.actor.hide(); - } - - - _onPreviewAnimationComplete() { - this._numPreviewsComplete += 1; - if (this._previews !== null && this._numPreviewsComplete >= this._previews.length) { - this.destroy(); - } - } - - destroy() { - if (this._haveModal) { - Main.popModal(this._grab); - this._haveModal = false; - } - - if (this._isAppSwitcher) { - if (this._subSwitchers != null) { - for (let switcher of this._subSwitchers.values()) { - switcher.destroy(); - } - } - } - - if (this._initialDelayTimeoutId !== 0) { - GLib.Source.remove(this._initialDelayTimeoutId); - } - - this._windows = null; - this._appWindowsMap = null; - this._subSwitchers = null; - this._windowTitles = null; - this._windowIconBoxes = null; - this._previews = null; - this._allPreviews = null; - this._initialDelayTimeoutId = null; - this._windowManager.disconnect(this._dcid); - this._windowManager.disconnect(this._mcid); - - if (this._parent === null) { global.window_group.show() }; - if (this._parent === null) this._manager.platform.removeBackground(); - - this._disablePerspectiveCorrection(); - Main.uiGroup.remove_child(this.actor); - } - - animateClosed(reason=CloseReason.ACTIVATE_SELECTED) { - if (this._animatingClosed) return; - this._animatingClosed = true; - let transition = 'userChoice'; - if (this._parent) { - this._ungrabModal(); - } - if (this._initialDelayTimeoutId === 0) { - // window title and icon - for (let window_title of this._windowTitles) { - this._manager.platform.tween(window_title, { - time: this._settings.animation_time, - opacity: 0, - transition: 'easeInOutQuint', - }); - } - for (let icon_box of this._windowIconBoxes) { - this._manager.platform.tween(icon_box, { - time: this._settings.animation_time, - opacity: 0, - transition: 'easeInOutQuint', - }); - } - - this._removeBackgroundEffects(); - - if (this._parent === null) this._manager.platform.lightenBackground(); - - // preview windows - let currentWorkspace = this._manager.workspace_manager.get_active_workspace(); - if (reason === CloseReason.ACTIVATE_SELECTED) { - for (let [i, preview] of this._previews.entries()) { - let metaWin = preview.metaWin; - - let animation_time = this._getRandomTime(); - if (i == this._currentIndex) { - animation_time = this._settings.animation_time; - } - preview.removeIcon(animation_time); - if (!metaWin.minimized && metaWin.get_workspace() === currentWorkspace) { - let rect = metaWin.get_buffer_rect(); - this._manager.platform.tween(preview, { - x: rect.x - this.actor.x, - y: rect.y - this.actor.y, - translation_x: 0, - scale_x: 1, - scale_y: 1, - scale_z: 1, - opacity: 255, - rotation_angle_y: 0.0, - onComplete: this._onPreviewAnimationComplete.bind(this), - time: animation_time, - transition: transition, - }); - } else { - let monitor = Main.layoutManager.monitors[preview.metaWin.get_monitor()]; - let pivot_point = preview.get_pivot_point_placement(Placement.TOP_LEFT); - preview.make_bottom_layer(this.previewActor); - let animation_time = this._getRandomTime(); - this._manager.platform.tween(preview, { - x: monitor.x - this.actor.x, - y: monitor.y - this.actor.y, - translation_x: 0, - pivot_point: pivot_point, - rotation_angle_y: 0.0, - onComplete: this._onPreviewAnimationComplete.bind(this), - time: animation_time, - transition: transition, - }); - this._manager.platform.tween(preview, { - scale_x: 0, - scale_y: 0, - scale_z: 0, - opacity: 0, - time: 0.95 * animation_time, - transition: 'easeInOutQuint' - }); - } - } - for (let preview of this._allPreviews) { - preview.make_top_layer(this.previewActor); - let transient_for_window = preview.metaWin.get_transient_for(); - if (transient_for_window !== null) { - for (let p of this._allPreviews) { - if (p.metaWin == transient_for_window) { - this.previewActor.set_child_above_sibling(preview, p); - } - } - } - if (!this._previews.includes(preview) && preview.metaWin.get_workspace() == currentWorkspace && !preview.metaWin.minimized) { - let rect = preview.metaWin.get_buffer_rect(); - let atime = this._getRandomTime(); - this._manager.platform.tween(preview, { - x: rect.x - this.actor.x, - y: rect.y - this.actor.y, - translation_x: 0, - rotation_angle_y: 0.0, - time: atime, - transition: 'userChoice', - }); - this._manager.platform.tween(preview, { - scale_x: 1, - scale_y: 1, - scale_z: 1, - opacity: 255, - time: 0.5 * atime, - transition: 'easeInOutQuint', - }); - } - } - let current_preview = this._previews[Math.round(this._currentIndex)]; - let current_preview_transient = current_preview.metaWin.get_transient_for() - if (current_preview_transient !== null) { - for (let p of this._allPreviews) { - if (p.metaWin == current_preview_transient) { - p.make_top_layer(this.previewActor); - break; - } - } - } - current_preview.make_top_layer(this.previewActor); - for (let p of this._allPreviews) { - if (p.metaWin.get_transient_for() == current_preview.metaWin) { - this.previewActor.set_child_above_sibling(p, current_preview); - } - } - this._raiseIcons(); - } else { - let monitor = this._updateActiveMonitor(); - this._manager.platform.tween(this.actor, { - x: monitor.x, - y: monitor.y, - scale_x: 0, - scale_y: 0, - scale_z: 0, - opacity: 0, - time: 0.99*this._settings.animation_time, - transition: 'easeInOutQuint', - onComplete: this.destroy.bind(this), - }); - } - } else { - this.destroy(); - } - } - - /* Code that ensures redrawing even if the compositor thinks there - should be clipping. Necessary because nmoving the camera does - not move the clipping pov so the compositor thinks some things don't need - redrawing because they are blocked by other things, but that's only - true from the perspective of the centered camera. For some reason this - works better than the inhibitCulling method which doesn't seem to work. - - Code stolen from the blur my shell extension, blur-my-shell@aunetx.*/ - /// Add the Clutter debug flag. - _disable_clipped_redraws() { - Meta.add_clutter_debug_flags( - null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null - ); - } - - /// Remove the Clutter debug flag. - _reenable_clipped_redraws() { - Meta.remove_clutter_debug_flags( - null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null - ); - } - - /* - * - * The following code that centers the camera on an off-center monitor - * is taken from the Desktop Cube extension. - * https://github.com/Schneegans/Desktop-Cube/blob/fa07fba3016ede5049eace2c028a7ba34dae12ef/extension.js#L1032-L1174 - * - */ - - // Calls inhibit_culling on the given actor and recursively on all mapped children. - _inhibitCulling(actor) { - if (actor.mapped) { - actor.inhibit_culling(); - actor._culling_inhibited = true; - actor.get_children().forEach(c => this._inhibitCulling(c)); - } - }; - - // Calls uninhibit_culling on the given actor and recursively on all children. It will - // only call uninhibit_culling() on those actors which were inhibited before. - _uninhibitCulling(actor) { - if (actor._culling_inhibited) { - delete actor._culling_inhibited; - actor.uninhibit_culling(); - actor.get_children().forEach(c => this._uninhibitCulling(c)); - } - }; - // Usually, GNOME Shell uses one central perspective for all monitors combined. This - // results in a somewhat sheared appearance of the cube on multi-monitor setups where - // the primary monitor is not in the middle (or cubes are shown on multiple monitors). - // With the code below, we modify the projection and view matrices for each monitor so - // that each monitor uses its own central perspective. This seems to be possible on - // Wayland only. On X11, there's only one set of projection and view matrices for all - // monitors combined, so we tweak them so that the projection center is in the middle of - // the primary monitor. So it will at least only look bad on X11 if the cube is shown on - // all monitors... - _enablePerspectiveCorrection() { - if (this._settings.perspective_correction_method != "Move Camera") return; - if (this._parent != null) return; - this._disable_clipped_redraws(); - this._stageBeforeUpdateID = global.stage.connect('before-update', (stage, view) => { - // Do nothing if neither overview or desktop switcher are shown. - if (!this.actor.visible) { - return; - } - - // Usually, the virtual camera is positioned centered in front of the stage. We will - // move the virtual camera around. These variables will be the new stage-relative - // coordinates of the virtual camera. - let cameraX, cameraY; - - const activeMonitorRect = - global.display.get_monitor_geometry(this._activeMonitor); - - cameraX = this.actor.x + this.actor.width / 2; - cameraY = this.actor.y + this.actor.height / 2; - - // This is the offset to the original, centered camera position. Y is flipped due to - // some negative scaling at some point in Mutter. - const camOffsetX = stage.width / 2 - cameraX; - const camOffsetY = cameraY - stage.height / 2; - - const z_near = stage.perspective.z_near; - const z_far = stage.perspective.z_far; - - // The code below is copied from Mutter's Clutter. - // https://gitlab.gnome.org/GNOME/mutter/-/blob/main/clutter/clutter/clutter-stage.c#L2255 - const A = 0.57735025882720947265625; - const B = 0.866025388240814208984375; - const C = 0.86162912845611572265625; - const D = 0.00872653536498546600341796875; - - const z_2d = z_near * A * B * C / D + z_near; - - // The code below is copied from Mutter's Clutter as well. - // https://gitlab.gnome.org/GNOME/mutter/-/blob/main/clutter/clutter/clutter-stage.c#L2270 - const top = z_near * Math.tan(stage.perspective.fovy * Math.PI / 360.0); - const left = -top * stage.perspective.aspect; - const right = top * stage.perspective.aspect; - const bottom = -top; - - const left_2d_plane = left / z_near * z_2d; - const right_2d_plane = right / z_near * z_2d; - const bottom_2d_plane = bottom / z_near * z_2d; - const top_2d_plane = top / z_near * z_2d; - - const width_2d_start = right_2d_plane - left_2d_plane; - const height_2d_start = top_2d_plane - bottom_2d_plane; - - const width_scale = width_2d_start / stage.width; - const height_scale = height_2d_start / stage.height; - // End of the copy-paste code. - - // Compute the required offset of the frustum planes at the near plane. This - // basically updates the projection matrix according to our new camera position. - const offsetX = camOffsetX * width_scale / z_2d * z_near; - const offsetY = camOffsetY * height_scale / z_2d * z_near; - - // Set the new frustum. - view.get_framebuffer().frustum(left + offsetX, right + offsetX, bottom + offsetY, - top + offsetY, z_near, z_far); - - // Translate the virtual camera. This basically updates the view matrix according to - // our new camera position. - view.get_framebuffer().push_matrix(); - view.get_framebuffer().translate(camOffsetX * width_scale, - camOffsetY * height_scale, 0); - - this._inhibitCulling(this.actor); - }); - - // Revert the matrix changes before the update, - this._stageAfterUpdateID = global.stage.connect('after-update', (stage, view) => { - // Nothing to do if neither overview or desktop switcher are shown. - if (!this.actor.visible) { - return; - } - - view.get_framebuffer().pop_matrix(); - view.get_framebuffer().perspective(stage.perspective.fovy, stage.perspective.aspect, - stage.perspective.z_near, - stage.perspective.z_far); - this._uninhibitCulling(this.actor); - }); - } - - // Reverts the changes done with the method above. - _disablePerspectiveCorrection() { - if (this._stageBeforeUpdateID) { - global.stage.disconnect(this._stageBeforeUpdateID); - this._stageBeforeUpdateID = 0; - } - - if (this._stageAfterUpdateID) { - global.stage.disconnect(this._stageAfterUpdateID); - this._stageAfterUpdateID = 0; - } - this._reenable_clipped_redraws(); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/timelineSwitcher.js b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/timelineSwitcher.js deleted file mode 100755 index 13d755f8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/timelineSwitcher.js +++ /dev/null @@ -1,293 +0,0 @@ -/* - This file is part of CoverflowAltTab. - - CoverflowAltTab is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - CoverflowAltTab is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with CoverflowAltTab. If not, see . -*/ - -/* CoverflowAltTab::TimelineSwitcher: - * - * Extends CoverflowAltTab::Switcher, switching tabs using a timeline - */ - -import {Switcher} from './switcher.js'; -import {Preview, Placement, findUpperLeftFromCenter} from './preview.js' - -let TRANSITION_TYPE; -let IN_BOUNDS_TRANSITION_TYPE; -const TILT_ANGLE = 45; - -export class TimelineSwitcher extends Switcher { - constructor(...args) { - super(...args); - TRANSITION_TYPE = 'userChoice'; - IN_BOUNDS_TRANSITION_TYPE = 'easeInOutQuint'; - } - - _createPreviews() { - let monitor = this._updateActiveMonitor(); - let currentWorkspace = this._manager.workspace_manager.get_active_workspace(); - - this._previewsCenterPosition = { - x: this.actor.width / 2, - y: this.actor.height / 2 + this._settings.offset - }; - - for (let windowActor of global.get_window_actors()) { - let metaWin = windowActor.get_meta_window(); - let compositor = metaWin.get_compositor_private(); - if (compositor) { - let texture = compositor.get_texture(); - let width, height; - if (texture.get_size) { - [width, height] = texture.get_size() - } else { - let preferred_size_ok; - [preferred_size_ok, width, height] = texture.get_preferred_size(); - } - let previewScale = this._settings.preview_to_monitor_ratio; - let scale = 1.0; - let previewWidth = this.actor.width * previewScale; - let previewHeight = this.actor.height * previewScale; - if (width > previewWidth || height > previewHeight) - scale = Math.min(previewWidth / width, previewHeight / height); - - let preview = new Preview(metaWin, this, { - opacity: (!metaWin.minimized && metaWin.get_workspace() == currentWorkspace || metaWin.is_on_all_workspaces()) ? 255: 0, - source: texture.get_size ? texture : compositor, - reactive: true, - name: metaWin.title, - x: (metaWin.minimized ? -(compositor.x + compositor.width / 2) : - compositor.x) - monitor.x, - y: (metaWin.minimized ? -(compositor.y + compositor.height / 2) : - compositor.y) - monitor.y, - rotation_angle_y: 0, - width: width, - height: height, - }); - - preview.scale = scale; - - preview.target_x = findUpperLeftFromCenter(preview.width * preview.scale, - this._previewsCenterPosition.x); - preview.target_y = findUpperLeftFromCenter(preview.height, - this._previewsCenterPosition.y); - - preview.set_pivot_point_placement(Placement.LEFT); - - if (this._windows.includes(metaWin)) { - this._previews[this._windows.indexOf(metaWin)] = preview; - } - this._allPreviews.push(preview); - this.previewActor.add_child(preview); - - preview.make_bottom_layer(this.previewActor); - } - } - } - - _previewNext() { - this._setCurrentIndex((this._currentIndex + 1) % this._windows.length); - this._updatePreviews(false, 1); - } - - _previewPrevious() { - this._setCurrentIndex((this._windows.length + this._currentIndex - 1) % this._windows.length); - this._updatePreviews(false, -1); - } - - _updatePreviews(reorder_only=false, direction=0) { - if (this._previews == null || this._previews.length == 0) - return; - - let animation_time = this._settings.animation_time * (this._settings.randomize_animation_times ? this._getRandomArbitrary(0.25, 1) : 1); - - if (this._previews.length == 1) { - if (reorder_only) return; - let preview = this._previews[0]; - this._manager.platform.tween(preview, { - x: preview.target_x, - y: preview.target_y, - scale_x: preview.scale, - scale_y: preview.scale, - scale_z: preview.scale, - time: animation_time / 2, - transition: TRANSITION_TYPE, - rotation_angle_y: TILT_ANGLE, - }); - this._manager.platform.tween(preview, { - opacity: 255, - time: animation_time / 2, - transition: IN_BOUNDS_TRANSITION_TYPE, - onComplete: () => { - preview.set_reactive(true); - } - }); - return; - } - - for (let i = this._currentIndex; i < this._currentIndex + this._previews.length; i++) { - this._previews[i%this._previews.length].make_bottom_layer(this.previewActor); - } - if (reorder_only) return; - // preview windows - for (let [i, preview] of this._previews.entries()) { - animation_time = this._settings.animation_time * (this._settings.randomize_animation_times ? this._getRandomArbitrary(0.0001, 1) : 1); - let distance = (this._currentIndex > i) ? this._previews.length - this._currentIndex + i : i - this._currentIndex; - if (distance === this._previews.length - 1 && direction > 0) { - preview.__looping = true; - animation_time = this._settings.animation_time; - preview.make_top_layer(this.previewActor); - this._raiseIcons(); - let scale = preview.scale * Math.pow(this._settings.preview_scaling_factor, -1); - this._manager.platform.tween(preview, { - x: preview.target_x + 150, - y: preview.target_y + 100, - time: animation_time / 2, - transition: TRANSITION_TYPE, - rotation_angle_y: TILT_ANGLE, - onCompleteParams: [preview, distance, animation_time], - onComplete: this._onFadeForwardComplete, - onCompleteScope: this, - }); - this._manager.platform.tween(preview, { - opacity: 0, - scale_x: scale, - scale_y: scale, - scale_z: scale, - time: animation_time / 2, - transition: IN_BOUNDS_TRANSITION_TYPE, - }); - } else if (distance === 0 && direction < 0) { - preview.__looping = true; - animation_time = this._settings.animation_time; - let scale = preview.scale * Math.pow(this._settings.preview_scaling_factor, this._previews.length); - preview.make_bottom_layer(this.previewActor); - this._manager.platform.tween(preview, { - time: animation_time / 2, - x: preview.target_x - Math.sqrt(this._previews.length) * 150, - y: preview.target_y - Math.sqrt(this._previews.length) * 100, - transition: TRANSITION_TYPE, - rotation_angle_y: TILT_ANGLE, - onCompleteParams: [preview, distance, animation_time], - onComplete: this._onFadeBackwardsComplete, - onCompleteScope: this, - }); - this._manager.platform.tween(preview, { - time: animation_time / 2, - transition: IN_BOUNDS_TRANSITION_TYPE, - scale_x: scale, - scale_y: scale, - scale_x: scale, - opacity: 0, - }); - } else { - let scale = preview.scale * Math.pow(this._settings.preview_scaling_factor, distance);//Math.max(preview.scale * ((20 - 2 * distance) / 20), 0); - let tweenparams = { - x: preview.target_x - Math.sqrt(distance) * 150, - y: preview.target_y - Math.sqrt(distance) * 100, - scale_x: scale, - scale_y: scale, - scale_z: scale, - time: animation_time, - rotation_angle_y: TILT_ANGLE, - transition: TRANSITION_TYPE, - onComplete: () => { preview.set_reactive(true); }, - - }; - let opacitytweenparams = { - opacity: 255, - time: animation_time, - transition: IN_BOUNDS_TRANSITION_TYPE, - }; - if (preview.__looping || preview.__finalTween) - preview.__finalTween = [tweenparams, opacitytweenparams]; - else - this._manager.platform.tween(preview, tweenparams); - this._manager.platform.tween(preview, opacitytweenparams); - } - } - } - - _onFadeBackwardsComplete(preview, distance, animation_time) { - preview.__looping = false; - preview.make_top_layer(this.previewActor); - this._raiseIcons(); - preview.x = preview.target_x + 150; - preview.y = preview.target_y + 100; - let scale_start = preview.scale * Math.pow(this._settings.preview_scaling_factor, -1); - preview.scale_x = scale_start; - preview.scale_y = scale_start; - preview.scale_z = scale_start; - - this._manager.platform.tween(preview, { - x: preview.target_x, - y: preview.target_y, - time: animation_time / 2, - transition: TRANSITION_TYPE, - onCompleteParams: [preview], - onComplete: this._onFinishMove, - onCompleteScope: this, - }); - this._manager.platform.tween(preview, { - opacity: 255, - scale_x: preview.scale, - scale_y: preview.scale, - scale_z: preview.scale, - time: animation_time / 2, - transition: IN_BOUNDS_TRANSITION_TYPE, - }); - } - - _onFadeForwardComplete(preview, distance, animation_time) { - preview.__looping = false; - preview.make_bottom_layer(this.previewActor); - log(distance); - - preview.x = preview.target_x - Math.sqrt(distance + 1) * 150; - preview.y = preview.target_y - Math.sqrt(distance + 1) * 100; - let scale_start = preview.scale * Math.pow(this._settings.preview_scaling_factor, distance + 1); - preview.scale_x = scale_start; - preview.scale_y = scale_start; - preview.scale_z = scale_start; - this._manager.platform.tween(preview, { - x: preview.target_x - Math.sqrt(distance) * 150, - y: preview.target_y - Math.sqrt(distance) * 100, - time: animation_time / 2, - transition: TRANSITION_TYPE, - onCompleteParams: [preview], - onComplete: this._onFinishMove, - onCompleteScope: this, - }); - let scale_end = preview.scale * Math.pow(this._settings.preview_scaling_factor, distance); - this._manager.platform.tween(preview, { - opacity: 255, - scale_x: scale_end, - scale_y: scale_end, - scale_z: scale_end, - time: animation_time / 2, - transition: IN_BOUNDS_TRANSITION_TYPE, - }); - } - - _onFinishMove(preview) { - this._updatePreviews(true) - - if (preview.__finalTween) { - for (let tween of preview.__finalTween) { - this._manager.platform.tween(preview, tween); - } - preview.__finalTween = null; - } - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/applications-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/applications-symbolic.svg deleted file mode 100755 index 87f307f5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/applications-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/code-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/code-symbolic.svg deleted file mode 100755 index 587c3d3e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/code-symbolic.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/contribute-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/contribute-symbolic.svg deleted file mode 100755 index 67bb36f8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/contribute-symbolic.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/coverflow-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/coverflow-symbolic.svg deleted file mode 100755 index 7960adac..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/coverflow-symbolic.svg +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/dash-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/dash-symbolic.svg deleted file mode 100755 index 5a78b467..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/dash-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/general-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/general-symbolic.svg deleted file mode 100755 index e11da07f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/general-symbolic.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/support-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/support-symbolic.svg deleted file mode 100755 index 67bb36f8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/support-symbolic.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/translate-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/translate-symbolic.svg deleted file mode 100755 index 43a33356..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/CoverflowAltTab@palatis.blogspot.com/ui/icons/hicolor/scalable/actions/translate-symbolic.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js deleted file mode 100755 index ff95f790..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js +++ /dev/null @@ -1,1591 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import St from 'gi://St'; - -import * as Params from 'resource:///org/gnome/shell/misc/params.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as IconCache from './iconCache.js'; -import * as Util from './util.js'; -import * as Interfaces from './interfaces.js'; -import * as PixmapsUtils from './pixmapsUtils.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as SettingsManager from './settingsManager.js'; -import {DBusProxy} from './dbusProxy.js'; - -Gio._promisify(Gio.File.prototype, 'read_async'); -Gio._promisify(GdkPixbuf.Pixbuf, 'get_file_info_async'); -Gio._promisify(GdkPixbuf.Pixbuf, 'new_from_stream_at_scale_async', - 'new_from_stream_finish'); -Gio._promisify(St.IconInfo.prototype, 'load_symbolic_async'); -Gio._promisify(Gio.DBusConnection.prototype, 'call'); - -const MAX_UPDATE_FREQUENCY = 30; // In ms -const FALLBACK_ICON_NAME = 'image-loading-symbolic'; -const PIXMAPS_FORMAT = imports.gi.Cogl.PixelFormat.ARGB_8888; - -export const SNICategory = Object.freeze({ - APPLICATION: 'ApplicationStatus', - COMMUNICATIONS: 'Communications', - SYSTEM: 'SystemServices', - HARDWARE: 'Hardware', -}); - -export const SNIStatus = Object.freeze({ - PASSIVE: 'Passive', - ACTIVE: 'Active', - NEEDS_ATTENTION: 'NeedsAttention', -}); - -const SNIconType = Object.freeze({ - NORMAL: 0, - ATTENTION: 1, - OVERLAY: 2, - - toPropertyName: (iconType, params = {isPixbuf: false}) => { - let propertyName = 'Icon'; - - if (iconType === SNIconType.OVERLAY) - propertyName = 'OverlayIcon'; - else if (iconType === SNIconType.ATTENTION) - propertyName = 'AttentionIcon'; - - return `${propertyName}${params.isPixbuf ? 'Pixmap' : 'Name'}`; - }, -}); - -export const AppIndicatorProxy = GObject.registerClass( -class AppIndicatorProxy extends DBusProxy { - static get interfaceInfo() { - if (!this._interfaceInfo) { - this._interfaceInfo = Gio.DBusInterfaceInfo.new_for_xml( - Interfaces.StatusNotifierItem); - } - return this._interfaceInfo; - } - - static get OPTIONAL_PROPERTIES() { - return [ - 'XAyatanaLabel', - 'XAyatanaLabelGuide', - 'XAyatanaOrderingIndex', - 'IconAccessibleDesc', - 'AttentionAccessibleDesc', - ]; - } - - static get TUPLE_TYPE() { - if (!this._tupleType) - this._tupleType = new GLib.VariantType('()'); - - return this._tupleType; - } - - static destroy() { - delete this._interfaceInfo; - delete this._tupleType; - } - - _init(busName, objectPath) { - const {interfaceInfo} = AppIndicatorProxy; - - super._init(busName, objectPath, interfaceInfo, - Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES); - - this.set_cached_property('Status', - new GLib.Variant('s', SNIStatus.PASSIVE)); - - - this._accumulatedProperties = new Set(); - this._cancellables = new Map(); - this._changedProperties = Object.create(null); - } - - async initAsync(cancellable) { - await super.initAsync(cancellable); - - this._setupProxyPropertyList(); - } - - destroy() { - const cachedProperties = this.get_cached_property_names(); - if (cachedProperties) { - cachedProperties.forEach(propertyName => - this.set_cached_property(propertyName, null)); - } - - super.destroy(); - } - - _onNameOwnerChanged() { - this._resetNeededProperties(); - - if (!this.gNameOwner) - this._cancelRefreshProperties(); - else - this._setupProxyPropertyList(); - } - - _setupProxyPropertyList() { - this._propertiesList = - (this.get_cached_property_names() || []).filter(p => - this.gInterfaceInfo.properties.some(pInfo => pInfo.name === p)); - - if (this._propertiesList.length) { - AppIndicatorProxy.OPTIONAL_PROPERTIES.forEach( - p => this._addExtraProperty(p)); - } - } - - _addExtraProperty(name) { - if (this._propertiesList.includes(name)) - return; - - if (!(name in this)) { - Object.defineProperty(this, name, { - configurable: false, - enumerable: true, - get: () => { - const v = this.get_cached_property(name); - return v ? v.deep_unpack() : null; - }, - }); - } - - this._propertiesList.push(name); - } - - _signalToPropertyName(signal) { - if (signal.startsWith('New')) - return signal.substr(3); - else if (signal.startsWith('XAyatanaNew')) - return `XAyatana${signal.substr(11)}`; - - return null; - } - - // The Author of the spec didn't like the PropertiesChanged signal, so he invented his own - async _refreshOwnProperties(prop) { - await Promise.all( - [prop, `${prop}Name`, `${prop}Pixmap`, `${prop}AccessibleDesc`].filter(p => - this._propertiesList.includes(p)).map(async p => { - try { - await this.refreshProperty(p, { - skipEqualityCheck: p.endsWith('Pixmap'), - }); - } catch (e) { - if (!AppIndicatorProxy.OPTIONAL_PROPERTIES.includes(p) || - !e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_PROPERTY)) - logError(e); - } - })); - } - - _onSignal(sender, signal, ...args) { - this._onSignalAsync(sender, signal, ...args).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, `Error while processing signal '${signal}'`); - }); - } - - async _onSignalAsync(_sender, signal, params) { - const property = this._signalToPropertyName(signal); - if (!property) - return; - - if (this.status === SNIStatus.PASSIVE && - ![...AppIndicator.NEEDED_PROPERTIES, 'Status'].includes(property)) { - this._accumulatedProperties.add(property); - return; - } - - if (!params.get_type().equal(AppIndicatorProxy.TUPLE_TYPE)) { - // If the property includes arguments, we can just queue the signal emission - const [value] = params.unpack(); - try { - await this._queuePropertyUpdate(property, value); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } - - if (!this._accumulatedProperties.size) - return; - } else { - this._accumulatedProperties.add(property); - } - - if (this._signalsAccumulator) - return; - - this._signalsAccumulator = new PromiseUtils.TimeoutPromise( - MAX_UPDATE_FREQUENCY, GLib.PRIORITY_DEFAULT_IDLE, this._cancellable); - try { - await this._signalsAccumulator; - const refreshPropertiesPromises = - [...this._accumulatedProperties].map(p => - this._refreshOwnProperties(p)); - this._accumulatedProperties.clear(); - await Promise.all(refreshPropertiesPromises); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } finally { - delete this._signalsAccumulator; - } - } - - _resetNeededProperties() { - AppIndicator.NEEDED_PROPERTIES.forEach(p => - this.set_cached_property(p, null)); - } - - async refreshAllProperties() { - const cancellableName = 'org.freedesktop.DBus.Properties.GetAll'; - const cancellable = this._cancelRefreshProperties({ - propertyName: cancellableName, - addNew: true, - }); - - try { - const [valuesVariant] = (await this.getProperties( - cancellable)).deep_unpack(); - - this._cancellables.delete(cancellableName); - - await Promise.all( - Object.entries(valuesVariant).map(([propertyName, valueVariant]) => - this._queuePropertyUpdate(propertyName, valueVariant, { - skipEqualityCheck: true, - cancellable, - }))); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - // the property may not even exist, silently ignore it - Util.Logger.debug(`While refreshing all properties: ${e}`); - - this.get_cached_property_names().forEach(propertyName => - this.set_cached_property(propertyName, null)); - - this._cancellables.delete(cancellableName); - throw e; - } - } - } - - async refreshProperty(propertyName, params) { - params = Params.parse(params, { - skipEqualityCheck: false, - }); - - const cancellable = this._cancelRefreshProperties({ - propertyName, - addNew: true, - }); - - try { - const [valueVariant] = (await this.getProperty( - propertyName, cancellable)).deep_unpack(); - - this._cancellables.delete(propertyName); - await this._queuePropertyUpdate(propertyName, valueVariant, - Object.assign(params, {cancellable})); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - // the property may not even exist, silently ignore it - Util.Logger.debug(`While refreshing property ${propertyName}: ${e}`); - this.set_cached_property(propertyName, null); - this._cancellables.delete(propertyName); - delete this._changedProperties[propertyName]; - throw e; - } - } - } - - async _queuePropertyUpdate(propertyName, value, params) { - params = Params.parse(params, { - skipEqualityCheck: false, - cancellable: null, - }); - - if (!params.skipEqualityCheck) { - const cachedProperty = this.get_cached_property(propertyName); - - if (value && cachedProperty && - value.equal(this.get_cached_property(propertyName))) - return; - } - - this.set_cached_property(propertyName, value); - - // synthesize a batched property changed event - this._changedProperties[propertyName] = value; - - if (!this._propertiesEmitTimeout || !this._propertiesEmitTimeout.pending()) { - if (!params.cancellable) { - params.cancellable = this._cancelRefreshProperties({ - propertyName, - addNew: true, - }); - } - this._propertiesEmitTimeout = new PromiseUtils.TimeoutPromise( - MAX_UPDATE_FREQUENCY * 2, GLib.PRIORITY_DEFAULT_IDLE, params.cancellable); - await this._propertiesEmitTimeout; - - if (Object.keys(this._changedProperties).length) { - this.emit('g-properties-changed', GLib.Variant.new('a{sv}', - this._changedProperties), []); - this._changedProperties = Object.create(null); - } - } - } - - _cancelRefreshProperties(params) { - params = Params.parse(params, { - propertyName: undefined, - addNew: false, - }); - - if (!this._cancellables.size && !params.addNew) - return null; - - if (params.propertyName !== undefined) { - let cancellable = this._cancellables.get(params.propertyName); - if (cancellable) { - cancellable.cancel(); - - if (!params.addNew) - this._cancellables.delete(params.propertyName); - } - - if (params.addNew) { - cancellable = new Util.CancellableChild(this._cancellable); - this._cancellables.set(params.propertyName, cancellable); - return cancellable; - } - } else { - this._cancellables.forEach(c => c.cancel()); - this._cancellables.clear(); - this._changedProperties = Object.create(null); - } - - return null; - } -}); - -/** - * the AppIndicator class serves as a generic container for indicator information and functions common - * for every displaying implementation (IndicatorMessageSource and IndicatorStatusIcon) - */ -export class AppIndicator extends Signals.EventEmitter { - static get NEEDED_PROPERTIES() { - return ['Id', 'Menu']; - } - - constructor(service, busName, object) { - super(); - - this.isReady = false; - this.busName = busName; - this._uniqueId = Util.indicatorId(service, busName, object); - - this._cancellable = new Gio.Cancellable(); - this._proxy = new AppIndicatorProxy(busName, object); - this._invalidatedPixmapsIcons = new Set(); - - this._setupProxy().catch(logError); - Util.connectSmart(this._proxy, 'g-properties-changed', this, this._onPropertiesChanged); - Util.connectSmart(this._proxy, 'notify::g-name-owner', this, this._nameOwnerChanged); - - if (this.uniqueId === service) { - this._nameWatcher = new Util.NameWatcher(service); - Util.connectSmart(this._nameWatcher, 'changed', this, this._nameOwnerChanged); - } - } - - async _setupProxy() { - const cancellable = this._cancellable; - - try { - await this._proxy.initAsync(cancellable); - this._checkIfReady(); - await this._checkNeededProperties(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - logError(e, `While initalizing proxy for ${this._uniqueId}`); - this.destroy(); - } - } - - // We try to lookup the activate method to see if the app supports it - try { - const introspectionVariant = await this._proxy.gConnection.call( - this._proxy.gNameOwner, this._proxy.gObjectPath, - 'org.freedesktop.DBus.Introspectable', 'Introspect', null, null, - Gio.DBusCallFlags.NONE, -1, cancellable); - const [introspectionXml] = introspectionVariant.deep_unpack(); - const nodeInfo = Gio.DBusNodeInfo.new_for_xml(introspectionXml); - const interfaceInfo = nodeInfo.lookup_interface(this._proxy.gInterfaceName); - this.supportsActivation = !!interfaceInfo.lookup_method('Activate'); - this._hasAyatanaSecondaryActivate = - !!interfaceInfo.lookup_method('XAyatanaSecondaryActivate'); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.debug( - `${this.uniqueId}, check for Activation support: ${e.message}`); - } - } - - try { - this._commandLine = await Util.getProcessName(this.busName, - cancellable, GLib.PRIORITY_LOW); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.debug( - `${this.uniqueId}, failed getting command line: ${e.message}`); - } - } - } - - _checkIfReady() { - const wasReady = this.isReady; - let isReady = false; - - if (this.hasNameOwner && this.id && this.menuPath) - isReady = true; - - this.isReady = isReady; - - if (this.isReady && !wasReady) { - if (this._delayCheck) { - this._delayCheck.cancel(); - delete this._delayCheck; - } - - this.emit('ready'); - return true; - } - - return false; - } - - async _checkNeededProperties() { - if (this.id && this.menuPath) - return true; - - const MAX_RETRIES = 3; - const cancellable = this._cancellable; - for (let checks = 0; checks < MAX_RETRIES; ++checks) { - this._delayCheck = new PromiseUtils.TimeoutSecondsPromise(1, - GLib.PRIORITY_DEFAULT_IDLE, cancellable); - // eslint-disable-next-line no-await-in-loop - await this._delayCheck; - - try { - // eslint-disable-next-line no-await-in-loop - await Promise.all(AppIndicator.NEEDED_PROPERTIES.map(p => - this._proxy.refreshProperty(p))); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - - if (checks < MAX_RETRIES - 1) - continue; - - throw e; - } - - if (this.id && this.menuPath) - break; - } - - return this.id && this.menuPath; - } - - async _nameOwnerChanged() { - if (!this.hasNameOwner) { - this._checkIfReady(); - } else { - try { - await this._checkNeededProperties(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.warn(`${this.uniqueId}, Impossible to get basic properties: ${e}`); - this.checkAlive(); - } - } - } - - this.emit('name-owner-changed'); - } - - // public property getters - get title() { - return this._proxy.Title; - } - - get id() { - return this._proxy.Id; - } - - get uniqueId() { - return this._uniqueId; - } - - get status() { - return this._proxy.Status; - } - - get label() { - return this._proxy.XAyatanaLabel || null; - } - - get accessibleName() { - const accessibleDesc = this.status === SNIStatus.NEEDS_ATTENTION - ? this._proxy.AccessibleDesc : this._proxy.IconAccessibleDesc; - - return accessibleDesc || this.title; - } - - get menuPath() { - if (this._proxy.Menu === '/NO_DBUSMENU') - return null; - - return this._proxy.Menu; - } - - get attentionIcon() { - return { - theme: this._proxy.IconThemePath, - name: this._proxy.AttentionIconName, - pixmap: this._getPixmapProperty(SNIconType.ATTENTION), - }; - } - - get icon() { - return { - theme: this._proxy.IconThemePath, - name: this._proxy.IconName, - pixmap: this._getPixmapProperty(SNIconType.NORMAL), - }; - } - - get overlayIcon() { - return { - theme: this._proxy.IconThemePath, - name: this._proxy.OverlayIconName, - pixmap: this._getPixmapProperty(SNIconType.OVERLAY), - }; - } - - get hasOverlayIcon() { - const {name, pixmap} = this.overlayIcon; - - return name || (pixmap && pixmap.n_children()); - } - - get hasNameOwner() { - if (this._nameWatcher && !this._nameWatcher.nameOnBus) - return false; - return !!this._proxy.g_name_owner; - } - - get cancellable() { - return this._cancellable; - } - - async checkAlive() { - // Some applications (hey electron!) just remove the indicator object - // from bus after hiding it, without closing its bus name, so we are - // not able to understand whe they're gone. - // Thus we just kill it when an expected well-known method is failing. - if (this.status !== SNIStatus.PASSIVE && this._checkIfReady()) { - if (this._checkAliveTimeout) { - this._checkAliveTimeout.cancel(); - delete this._checkAliveTimeout; - } - return; - } - - if (this._checkAliveTimeout) - return; - - try { - const cancellable = this._cancellable; - this._checkAliveTimeout = new PromiseUtils.TimeoutSecondsPromise(10, - GLib.PRIORITY_DEFAULT_IDLE, cancellable); - Util.Logger.debug(`${this.uniqueId}: may not respond, checking...`); - await this._checkAliveTimeout; - - // We should call the Ping method instead but in some containers - // such as snaps that's not accessible, so let's just use our own - await this._proxy.getProperty('Status', cancellable); - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.NAME_HAS_NO_OWNER) || - e.matches(Gio.DBusError, Gio.DBusError.SERVICE_UNKNOWN) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_OBJECT) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_INTERFACE) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD) || - e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_PROPERTY)) { - Util.Logger.warn(`${this.uniqueId}: not on bus anymore, removing it`); - this.destroy(); - return; - } - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - delete this._checkAliveTimeout; - } - } - - _onPropertiesChanged(_proxy, changed, _invalidated) { - const props = Object.keys(changed.unpack()); - const signalsToEmit = new Set(); - const checkIfReadyChanged = () => { - if (checkIfReadyChanged.value === undefined) - checkIfReadyChanged.value = this._checkIfReady(); - return checkIfReadyChanged.value; - }; - - props.forEach(property => { - // some property changes require updates on our part, - // a few need to be passed down to the displaying code - if (property === 'Id') - checkIfReadyChanged(); - - // all these can mean that the icon has to be changed - if (property.startsWith('Icon') || - property.startsWith('AttentionIcon')) - signalsToEmit.add('icon'); - - // same for overlays - if (property.startsWith('OverlayIcon')) - signalsToEmit.add('overlay-icon'); - - // this may make all of our icons invalid - if (property === 'IconThemePath') { - signalsToEmit.add('icon'); - signalsToEmit.add('overlay-icon'); - } - - // the label will be handled elsewhere - if (property === 'XAyatanaLabel') - signalsToEmit.add('label'); - - if (property === 'Menu') { - if (!checkIfReadyChanged() && this.isReady) - signalsToEmit.add('menu'); - } - - if (property === 'IconAccessibleDesc' || - property === 'AttentionAccessibleDesc' || - property === 'Title') - signalsToEmit.add('accessible-name'); - - // status updates may cause the indicator to be hidden - if (property === 'Status') { - signalsToEmit.add('icon'); - signalsToEmit.add('overlay-icon'); - signalsToEmit.add('status'); - signalsToEmit.add('accessible-name'); - } - }); - - signalsToEmit.forEach(s => this.emit(s)); - } - - reset() { - this.emit('reset'); - } - - destroy() { - this.emit('destroy'); - - this.disconnectAll(); - this._proxy.destroy(); - this._cancellable.cancel(); - this._invalidatedPixmapsIcons.clear(); - - if (this._nameWatcher) - this._nameWatcher.destroy(); - delete this._cancellable; - delete this._proxy; - delete this._nameWatcher; - } - - _getPixmapProperty(iconType) { - const propertyName = SNIconType.toPropertyName(iconType, - {isPixbuf: true}); - const pixmap = this._proxy.get_cached_property(propertyName); - const wasInvalidated = this._invalidatedPixmapsIcons.delete(iconType); - - if (!pixmap && wasInvalidated) { - this._proxy.refreshProperty(propertyName, { - skipEqualityCheck: true, - }).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - return pixmap; - } - - invalidatePixmapProperty(iconType) { - this._invalidatedPixmapsIcons.add(iconType); - this._proxy.set_cached_property( - SNIconType.toPropertyName(iconType, {isPixbuf: true}), null); - } - - _getActivationToken(timestamp) { - const launchContext = global.create_app_launch_context(timestamp, -1); - const fakeAppInfo = Gio.AppInfo.create_from_commandline( - this._commandLine || 'true', this.id, - Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION); - return [launchContext, launchContext.get_startup_notify_id(fakeAppInfo, [])]; - } - - async provideActivationToken(timestamp) { - if (this._hasProvideXdgActivationToken === false) - return; - - const [launchContext, activationToken] = this._getActivationToken(timestamp); - try { - await this._proxy.ProvideXdgActivationTokenAsync(activationToken, - this._cancellable); - this._hasProvideXdgActivationToken = true; - } catch (e) { - launchContext.launch_failed(activationToken); - - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) - this._hasProvideXdgActivationToken = false; - else - Util.Logger.warn(`${this.id}, failed to provide activation token: ${e.message}`); - } - } - - async open(x, y, timestamp) { - const cancellable = this._cancellable; - // we can't use WindowID because we're not able to get the x11 window id from a MetaWindow - // nor can we call any X11 functions. Luckily, the Activate method usually works fine. - // parameters are "an hint to the item where to show eventual windows" [sic] - // ... and don't seem to have any effect. - - try { - await this.provideActivationToken(timestamp); - await this._proxy.ActivateAsync(x, y, cancellable); - this.supportsActivation = true; - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) { - this.supportsActivation = false; - Util.Logger.warn(`${this.id}, does not support activation: ${e.message}`); - return; - } - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.critical(`${this.id}, failed to activate: ${e.message}`); - } - } - - async secondaryActivate(timestamp, x, y) { - const cancellable = this._cancellable; - - try { - await this.provideActivationToken(timestamp); - - if (this._hasAyatanaSecondaryActivate !== false) { - try { - await this._proxy.XAyatanaSecondaryActivateAsync(timestamp, cancellable); - this._hasAyatanaSecondaryActivate = true; - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD)) - this._hasAyatanaSecondaryActivate = false; - else - throw e; - } - } - - if (!this._hasAyatanaSecondaryActivate) - await this._proxy.SecondaryActivateAsync(x, y, cancellable); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.critical(`${this.id}, failed to secondary activate: ${e.message}`); - } - } - - async scroll(dx, dy) { - const cancellable = this._cancellable; - - try { - const actions = []; - - if (dx !== 0) { - actions.push(this._proxy.ScrollAsync(Math.floor(dx), - 'horizontal', cancellable)); - } - - if (dy !== 0) { - actions.push(this._proxy.ScrollAsync(Math.floor(dy), - 'vertical', cancellable)); - } - - await Promise.all(actions); - } catch (e) { - Util.Logger.critical(`${this.id}, failed to scroll: ${e.message}`); - } - } -} - -const StTextureCacheSkippingFileIcon = GObject.registerClass({ - Implements: [Gio.Icon], -}, class StTextureCacheSkippingFileIconImpl extends Gio.EmblemedIcon { - _init(params) { - // FIXME: We can't just inherit from Gio.FileIcon for some reason - super._init({gicon: new Gio.FileIcon(params)}); - } - - vfunc_to_tokens() { - // Disables the to_tokens() vfunc so that the icon to_string() - // method won't work and thus can't be kept forever around by - // StTextureCache, see the awesome debugging session in this thread: - // https://twitter.com/mild_sunrise/status/1458739604098621443 - // upstream bug is at: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4944 - return [false, [], 0]; - } -}); - -export const IconActor = GObject.registerClass( -class AppIndicatorsIconActor extends St.Icon { - static get DEFAULT_STYLE() { - return 'padding: 0'; - } - - static get USER_WRITABLE_PATHS() { - if (!this._userWritablePaths) { - this._userWritablePaths = [ - GLib.get_user_cache_dir(), - GLib.get_user_data_dir(), - GLib.get_user_config_dir(), - GLib.get_user_runtime_dir(), - GLib.get_home_dir(), - GLib.get_tmp_dir(), - ]; - - this._userWritablePaths.push(Object.values(GLib.UserDirectory).slice( - 0, -1).map(dirId => GLib.get_user_special_dir(dirId))); - } - - return this._userWritablePaths; - } - - _init(indicator, iconSize) { - super._init({ - reactive: true, - style_class: 'system-status-icon', - fallbackIconName: FALLBACK_ICON_NAME, - }); - - this.name = this.constructor.name; - this.add_style_class_name('appindicator-icon'); - this.add_style_class_name('status-notifier-icon'); - this.set_style(AppIndicatorsIconActor.DEFAULT_STYLE); - - const themeContext = St.ThemeContext.get_for_stage(global.stage); - this.height = iconSize * themeContext.scale_factor; - - this._indicator = indicator; - this._customIcons = new Map(); - this._iconSize = iconSize; - this._iconCache = new IconCache.IconCache(); - this._cancellable = new Gio.Cancellable(); - this._loadingIcons = Object.create(null); - - Object.values(SNIconType).forEach(t => (this._loadingIcons[t] = new Map())); - - Util.connectSmart(this._indicator, 'icon', this, () => { - if (this.is_mapped()) - this._updateIcon(); - }); - Util.connectSmart(this._indicator, 'overlay-icon', this, () => { - if (this.is_mapped()) - this._updateIcon(); - }); - Util.connectSmart(this._indicator, 'reset', this, - () => this._invalidateIconWhenFullyReady()); - - const settings = SettingsManager.getDefaultGSettings(); - Util.connectSmart(settings, 'changed::icon-size', this, () => - this._updateWhenFullyReady()); - Util.connectSmart(settings, 'changed::custom-icons', this, () => { - this._updateCustomIcons(); - this._invalidateIconWhenFullyReady(); - }); - - if (GObject.signal_lookup('resource-scale-changed', this)) - this.connect('resource-scale-changed', () => this._invalidateIcon()); - else - this.connect('notify::resource-scale', () => this._invalidateIcon()); - - Util.connectSmart(themeContext, 'notify::scale-factor', this, tc => { - this._updateIconSize(); - this.height = this._iconSize * tc.scale_factor; - this.width = -1; - this._invalidateIcon(); - }); - - Util.connectSmart(Util.getDefaultTheme(), 'changed', this, - () => this._invalidateIconWhenFullyReady()); - - this.connect('notify::mapped', () => { - if (!this.is_mapped()) - this._updateWhenFullyReady(); - }); - - this._updateWhenFullyReady(); - - this.connect('destroy', () => { - this._iconCache.destroy(); - this._cancellable.cancel(); - this._cancellable = null; - this._indicator = null; - this._loadingIcons = null; - this._iconTheme = null; - }); - } - - get debugId() { - return this._indicator ? this._indicator.id : this.toString(); - } - - async _waitForFullyReady() { - const waitConditions = []; - - if (!this.is_mapped()) { - waitConditions.push(new PromiseUtils.SignalConnectionPromise( - this, 'notify::mapped', this._cancellable)); - } - - if (!this._indicator.isReady) { - waitConditions.push(new PromiseUtils.SignalConnectionPromise( - this._indicator, 'ready', this._cancellable)); - } - - if (!waitConditions.length) - return true; - - await Promise.all(waitConditions); - return this._waitForFullyReady(); - } - - async _updateWhenFullyReady() { - if (this._waitingReady) - return; - - try { - this._waitingReady = true; - await this._waitForFullyReady(); - - this._updateIconSize(); - this._updateIconClass(); - this._updateCustomIcons(); - this._invalidateIcon(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - delete this._waitingReady; - } - } - - _updateIconClass() { - if (!this._indicator) - return; - - this.add_style_class_name( - `appindicator-icon-${this._indicator.id.toLowerCase().replace(/_|\s/g, '-')}`); - } - - _cancelLoadingByType(iconType) { - this._loadingIcons[iconType].forEach(c => c.cancel()); - this._loadingIcons[iconType].clear(); - } - - _ensureNoIconIsLoading(iconType, id) { - if (this._loadingIcons[iconType].has(id)) { - Util.Logger.debug(`${this.debugId}, Icon ${id} Is still loading, ignoring the request`); - throw new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING, - 'Already in progress'); - } else if (this._loadingIcons[iconType].size > 0) { - throw new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS, - 'Another icon is already loading'); - } - } - - _getIconLoadingCancellable(iconType, loadingId) { - try { - this._ensureNoIconIsLoading(iconType, loadingId); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) - throw e; - this._cancelLoadingByType(iconType); - } - - const cancellable = new Util.CancellableChild(this._cancellable); - this._loadingIcons[iconType].set(loadingId, cancellable); - - return cancellable; - } - - _cleanupIconLoadingCancellable(iconType, loadingId) { - if (this._loadingIcons) - this._loadingIcons[iconType].delete(loadingId); - } - - _getResourceScale() { - // Remove this when we remove support for versions earlier than 3.38 - const resourceScale = this.get_resource_scale(); - if (Array.isArray(resourceScale)) - return resourceScale[0] ? resourceScale[1] : 1.0; - - return resourceScale; - } - - // Will look the icon up in the cache, if it's found - // it will return it. Otherwise, it will create it and cache it. - async _cacheOrCreateIconByName(iconType, iconSize, iconScaling, iconName, themePath) { - const id = `${iconType}:${iconName}@${iconSize * iconScaling}:${themePath || ''}`; - let gicon = this._iconCache.get(id); - - if (gicon) - return gicon; - - const iconData = this._getIconData(iconName, themePath, iconSize, iconScaling); - const loadingId = iconData.file ? iconData.file.get_path() : id; - - const cancellable = await this._getIconLoadingCancellable(iconType, id); - try { - gicon = await this._createIconByIconData(iconData, iconSize, - iconScaling, cancellable); - } finally { - this._cleanupIconLoadingCancellable(iconType, loadingId); - } - if (gicon) - gicon = this._iconCache.add(id, gicon); - return gicon; - } - - _getIconLookupFlags(themeNode) { - let lookupFlags = 0; - - if (!themeNode) - return lookupFlags; - - const lookupFlagsEnum = St.IconLookupFlags; - const iconStyle = themeNode.get_icon_style(); - if (iconStyle === St.IconStyle.REGULAR) - lookupFlags |= lookupFlagsEnum.FORCE_REGULAR; - else if (iconStyle === St.IconStyle.SYMBOLIC) - lookupFlags |= lookupFlagsEnum.FORCE_SYMBOLIC; - - if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) - lookupFlags |= lookupFlagsEnum.DIR_RTL; - else - lookupFlags |= lookupFlagsEnum.DIR_LTR; - - return lookupFlags; - } - - async _createIconByIconData(iconData, iconSize, iconScaling, cancellable) { - const {file, name} = iconData; - - if (!file && !name) { - if (this._createIconIdle) { - throw new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING, - 'Already in progress'); - } - - try { - this._createIconIdle = new PromiseUtils.IdlePromise(GLib.PRIORITY_DEFAULT_IDLE, - cancellable); - await this._createIconIdle; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - throw e; - } finally { - delete this._createIconIdle; - } - return this.gicon; - } else if (this._createIconIdle) { - this._createIconIdle.cancel(); - delete this._createIconIdle; - } - - if (name) - return new Gio.ThemedIcon({name}); - - if (!file) - throw new Error('Neither file or name are set'); - - if (!this._isFileInWritableArea(file)) - return new Gio.FileIcon({file}); - - try { - const [format, width, height] = await GdkPixbuf.Pixbuf.get_file_info_async( - file.get_path(), cancellable); - - if (!format) { - Util.Logger.critical(`${this.debugId}, Invalid image format: ${file.get_path()}`); - return null; - } - - if (width >= height * 1.5) { - /* Hello indicator-multiload! */ - await this._loadCustomImage(file, - width, height, iconSize, iconScaling, cancellable); - return null; - } else { - /* We'll wrap the icon so that it won't be cached forever by the shell */ - return new StTextureCacheSkippingFileIcon({file}); - } - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Util.Logger.warn( - `${this.debugId}, Impossible to read image info from ` + - `path '${file ? file.get_path() : null}' or name '${name}': ${e}`); - } - throw e; - } - } - - async _loadCustomImage(file, width, height, iconSize, iconScaling, cancellable) { - const textureCache = St.TextureCache.get_default(); - const customImage = textureCache.load_file_async(file, -1, - height, 1, iconScaling); - - const setCustomImageActor = imageActor => { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const {content} = imageActor; - imageActor.content = null; - imageActor.destroy(); - - this._setImageContent(content, - width * scaleFactor, height * scaleFactor); - }; - - if (customImage.content) { - setCustomImageActor(customImage); - return; - } - - const imageContentPromise = new PromiseUtils.SignalConnectionPromise( - customImage, 'notify::content', cancellable); - const waitPromise = new PromiseUtils.TimeoutSecondsPromise( - 1, GLib.PRIORITY_DEFAULT, cancellable); - - const racingPromises = [imageContentPromise, waitPromise]; - - try { - await Promise.race(racingPromises); - if (!waitPromise.resolved()) - setCustomImageActor(customImage); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } finally { - racingPromises.forEach(p => p.cancel()); - } - } - - _isFileInWritableArea(file) { - // No need to use IO here, we can just do some assumptions - // print('Writable paths', IconActor.USER_WRITABLE_PATHS) - const path = file.get_path(); - return IconActor.USER_WRITABLE_PATHS.some(writablePath => - path.startsWith(writablePath)); - } - - _createIconTheme(searchPath = []) { - const iconTheme = new St.IconTheme(); - iconTheme.set_search_path(searchPath); - - return iconTheme; - } - - _getIconData(name, themePath, size, scale) { - const emptyIconData = {iconInfo: null, file: null, name: null}; - - if (!name) { - delete this._iconTheme; - return emptyIconData; - } - - // HACK: icon is a path name. This is not specified by the API, - // but at least indicator-sensors uses it. - if (name[0] === '/') { - delete this._iconTheme; - - const file = Gio.File.new_for_path(name); - return {file, iconInfo: null, name: null}; - } - - if (name.includes('.')) { - const splits = name.split('.'); - - if (['svg', 'png'].includes(splits[splits.length - 1])) - name = splits.slice(0, -1).join(''); - } - - if (themePath && Util.getDefaultTheme().get_search_path().includes(themePath)) - themePath = null; - - if (themePath) { - // If a theme path is provided, we need to lookup the icon ourself - // as St won't be able to do it unless we mess with default theme - // that is something we prefer not to do, as it would imply lots of - // St.TextureCache cleanups. - - const newSearchPath = [themePath]; - if (!this._iconTheme) { - this._iconTheme = this._createIconTheme(newSearchPath); - } else { - const currentSearchPath = this._iconTheme.get_search_path(); - - if (!currentSearchPath.includes(newSearchPath)) - this._iconTheme.set_search_path(newSearchPath); - } - - // try to look up the icon in the icon theme - const iconInfo = this._iconTheme.lookup_icon_for_scale(`${name}`, - size, scale, this._getIconLookupFlags(this.get_theme_node()) | - St.IconLookupFlags.GENERIC_FALLBACK); - - if (iconInfo) { - return { - iconInfo, - file: Gio.File.new_for_path(iconInfo.get_filename()), - name: null, - }; - } - - const logger = this.gicon ? Util.Logger.debug : Util.Logger.warn; - logger(`${this.debugId}, Impossible to lookup icon ` + - `for '${name}' in ${themePath}`); - - return emptyIconData; - } - - delete this._iconTheme; - return {name, iconInfo: null, file: null}; - } - - _setImageContent(content, width, height) { - this.set({ - content, - width, - height, - contentGravity: Clutter.ContentGravity.RESIZE_ASPECT, - fallbackIconName: null, - }); - } - - async _createIconFromPixmap(iconType, iconSize, iconScaling, scaleFactor, pixmapsVariant) { - const {pixmapVariant, width, height, rowStride} = - PixmapsUtils.getBestPixmap(pixmapsVariant, iconSize * iconScaling); - - const id = `__PIXMAP_ICON_${width}x${height}`; - - const imageContent = new St.ImageContent({ - preferredWidth: width, - preferredHeight: height, - }); - - imageContent.set_bytes(pixmapVariant.get_data_as_bytes(), PIXMAPS_FORMAT, - width, height, rowStride); - - if (iconType !== SNIconType.OVERLAY && !this._indicator.hasOverlayIcon) { - const scaledSize = iconSize * scaleFactor; - this._setImageContent(imageContent, scaledSize, scaledSize); - return null; - } - - const cancellable = this._getIconLoadingCancellable(iconType, id); - try { - // FIXME: async API results in a gray icon for some reason - const [inputStream] = imageContent.load(iconSize, cancellable); - return await GdkPixbuf.Pixbuf.new_from_stream_at_scale_async( - inputStream, -1, iconSize * iconScaling, true, cancellable); - } catch (e) { - // the image data was probably bogus. We don't really know why, but it _does_ happen. - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.warn(`${this.debugId}, Impossible to create image from data: ${e}`); - throw e; - } finally { - this._cleanupIconLoadingCancellable(iconType, id); - } - } - - // The icon cache Active flag will be set to true if the used gicon matches - // the cached one (as in some cases it may be equal, but not the same object). - // So when it's not need anymore we make sure to check the active state - // and set it to false so that it can be picked up by the garbage collector. - _setGicon(iconType, gicon) { - if (iconType !== SNIconType.OVERLAY) { - if (gicon) { - if (this.gicon === gicon || - (this.gicon && this.gicon.get_icon() === gicon)) - return; - - if (gicon instanceof Gio.EmblemedIcon) - this.gicon = gicon; - else - this.gicon = new Gio.EmblemedIcon({gicon}); - - this._iconCache.updateActive(SNIconType.NORMAL, gicon, - this.gicon.get_icon() === gicon); - } else { - this.gicon = null; - } - } else if (gicon) { - this._emblem = new Gio.Emblem({icon: gicon}); - this._iconCache.updateActive(iconType, gicon, true); - } else { - this._emblem = null; - } - - if (this.gicon) { - if (!this.gicon.get_emblems().some(e => e.equal(this._emblem))) { - this.gicon.clear_emblems(); - if (this._emblem) - this.gicon.add_emblem(this._emblem); - } - } - } - - async _updateIconByType(iconType, iconSize) { - let icon; - switch (iconType) { - case SNIconType.ATTENTION: - icon = this._indicator.attentionIcon; - break; - case SNIconType.NORMAL: - ({icon} = this._indicator); - break; - case SNIconType.OVERLAY: - icon = this._indicator.overlayIcon; - break; - } - - const {theme, name, pixmap} = icon; - const commonArgs = [theme, iconType, iconSize]; - - if (this._customIcons.size) { - let customIcon = this._customIcons.get(iconType); - if (!await this._createAndSetIcon(customIcon, null, ...commonArgs)) { - if (iconType !== SNIconType.OVERLAY) { - customIcon = this._customIcons.get(SNIconType.NORMAL); - await this._createAndSetIcon(customIcon, null, ...commonArgs); - } - } - } else { - await this._createAndSetIcon(name, pixmap, ...commonArgs); - } - } - - async _createAndSetIcon(name, pixmap, theme, iconType, iconSize) { - let gicon = null; - - try { - gicon = await this._createIcon(name, pixmap, theme, iconType, iconSize); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) || - e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) - return null; - - if (iconType === SNIconType.OVERLAY) { - logError(e, `${this.debugId} unable to update icon emblem`); - } else { - this.fallbackIconName = FALLBACK_ICON_NAME; - logError(e, `${this.debugId} unable to update icon`); - } - } - - try { - this._setGicon(iconType, gicon); - - if (pixmap && this.gicon) { - // The pixmap has been saved, we can free the variants memory - this._indicator.invalidatePixmapProperty(iconType); - } - - return gicon; - } catch (e) { - logError(e, 'Setting GIcon failed'); - return null; - } - } - - // updates the base icon - async _createIcon(name, pixmap, theme, iconType, iconSize) { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const resourceScale = this._getResourceScale(); - const iconScaling = Math.ceil(resourceScale * scaleFactor); - - // From now on we consider them the same thing, as one replaces the other - if (iconType === SNIconType.ATTENTION) - iconType = SNIconType.NORMAL; - - if (name) { - const gicon = await this._cacheOrCreateIconByName( - iconType, iconSize, iconScaling, name, theme); - if (gicon) - return gicon; - } - - if (pixmap && pixmap.n_children()) { - return this._createIconFromPixmap(iconType, - iconSize, iconScaling, scaleFactor, pixmap); - } - - return null; - } - - // updates the base icon - async _updateIcon() { - if (this._indicator.status === SNIStatus.PASSIVE) - return; - - if (this.gicon instanceof Gio.EmblemedIcon) { - const {gicon} = this.gicon; - this._iconCache.updateActive(SNIconType.NORMAL, gicon, false); - } - - // we might need to use the AttentionIcon*, which have precedence over the normal icons - const iconType = this._indicator.status === SNIStatus.NEEDS_ATTENTION - ? SNIconType.ATTENTION : SNIconType.NORMAL; - - try { - await this._updateIconByType(iconType, this._iconSize); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) && - !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) - logError(e, `${this.debugId}: Updating icon type ${iconType} failed`); - } - } - - async _updateOverlayIcon() { - if (this._indicator.status === SNIStatus.PASSIVE) - return; - - if (this._emblem) { - const {icon} = this._emblem; - this._iconCache.updateActive(SNIconType.OVERLAY, icon, false); - } - - // KDE hardcodes the overlay icon size to 10px (normal icon size 16px) - // we approximate that ratio for other sizes, too. - // our algorithms will always pick a smaller one instead of stretching it. - const iconSize = Math.floor(this._iconSize / 1.6); - - try { - await this._updateIconByType(SNIconType.OVERLAY, iconSize); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED) && - !e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) - logError(e, `${this.debugId}: Updating overlay icon failed`); - } - } - - async _invalidateIconWhenFullyReady() { - if (this._waitingInvalidation) - return; - - try { - this._waitingInvalidation = true; - await this._waitForFullyReady(); - this._invalidateIcon(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - delete this._waitingInvalidation; - } - } - - // called when the icon theme changes - _invalidateIcon() { - this._iconCache.clear(); - this._cancellable.cancel(); - this._cancellable = new Gio.Cancellable(); - Object.values(SNIconType).forEach(iconType => - this._loadingIcons[iconType].clear()); - - this._updateIcon().catch(e => logError(e)); - this._updateOverlayIcon().catch(e => logError(e)); - } - - _updateIconSize() { - const settings = SettingsManager.getDefaultGSettings(); - const sizeValue = settings.get_int('icon-size'); - - if (sizeValue > 0) { - if (!this._defaultIconSize) - this._defaultIconSize = this._iconSize; - - this._iconSize = sizeValue; - } else if (this._defaultIconSize) { - this._iconSize = this._defaultIconSize; - delete this._defaultIconSize; - } - - const themeIconSize = Math.round( - this.get_theme_node().get_length('icon-size')); - let iconStyle = AppIndicatorsIconActor.DEFAULT_STYLE; - - if (themeIconSize > 0) { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - - if (themeIconSize / scaleFactor !== this._iconSize) { - iconStyle = `${AppIndicatorsIconActor.DEFAULT_STYLE};` + - 'icon-size: 0'; - } - } - - this.set_style(iconStyle); - this.set_icon_size(this._iconSize); - } - - _updateCustomIcons() { - const settings = SettingsManager.getDefaultGSettings(); - this._customIcons.clear(); - - settings.get_value('custom-icons').deep_unpack().forEach(customIcons => { - const [indicatorId, normalIcon, attentionIcon] = customIcons; - if (this._indicator.id === indicatorId) { - this._customIcons.set(SNIconType.NORMAL, normalIcon); - this._customIcons.set(SNIconType.ATTENTION, attentionIcon); - } - }); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js deleted file mode 100755 index 6e8067d3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js +++ /dev/null @@ -1,965 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import Clutter from 'gi://Clutter'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import St from 'gi://St'; - -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as DBusInterfaces from './interfaces.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as Util from './util.js'; -import {DBusProxy} from './dbusProxy.js'; - -Gio._promisify(GdkPixbuf.Pixbuf, 'new_from_stream_async'); - -// //////////////////////////////////////////////////////////////////////// -// PART ONE: "ViewModel" backend implementation. -// Both code and design are inspired by libdbusmenu -// //////////////////////////////////////////////////////////////////////// - -/** - * Saves menu property values and handles type checking and defaults - */ -export class PropertyStore { - constructor(initialProperties) { - this._props = new Map(); - - if (initialProperties) { - for (const [prop, value] of Object.entries(initialProperties)) - this.set(prop, value); - } - } - - set(name, value) { - if (name in PropertyStore.MandatedTypes && value && - !value.is_of_type(PropertyStore.MandatedTypes[name])) - Util.Logger.warn(`Cannot set property ${name}: type mismatch!`); - else if (value) - this._props.set(name, value); - else - this._props.delete(name); - } - - get(name) { - const prop = this._props.get(name); - if (prop) - return prop; - else if (name in PropertyStore.DefaultValues) - return PropertyStore.DefaultValues[name]; - else - return null; - } -} - -// we list all the properties we know and use here, so we won' have to deal with unexpected type mismatches -PropertyStore.MandatedTypes = { - 'visible': GLib.VariantType.new('b'), - 'enabled': GLib.VariantType.new('b'), - 'label': GLib.VariantType.new('s'), - 'type': GLib.VariantType.new('s'), - 'children-display': GLib.VariantType.new('s'), - 'icon-name': GLib.VariantType.new('s'), - 'icon-data': GLib.VariantType.new('ay'), - 'toggle-type': GLib.VariantType.new('s'), - 'toggle-state': GLib.VariantType.new('i'), -}; - -PropertyStore.DefaultValues = { - 'visible': GLib.Variant.new_boolean(true), - 'enabled': GLib.Variant.new_boolean(true), - 'label': GLib.Variant.new_string(''), - 'type': GLib.Variant.new_string('standard'), - // elements not in here must return null -}; - -/** - * Represents a single menu item - */ -export class DbusMenuItem extends Signals.EventEmitter { - // will steal the properties object - constructor(client, id, properties, childrenIds) { - super(); - - this._client = client; - this._id = id; - this._propStore = new PropertyStore(properties); - this._children_ids = childrenIds; - } - - propertyGet(propName) { - const prop = this.propertyGetVariant(propName); - return prop ? prop.get_string()[0] : null; - } - - propertyGetVariant(propName) { - return this._propStore.get(propName); - } - - propertyGetBool(propName) { - const prop = this.propertyGetVariant(propName); - return prop ? prop.get_boolean() : false; - } - - propertyGetInt(propName) { - const prop = this.propertyGetVariant(propName); - return prop ? prop.get_int32() : 0; - } - - propertySet(prop, value) { - this._propStore.set(prop, value); - - this.emit('property-changed', prop, this.propertyGetVariant(prop)); - } - - resetProperties() { - Object.entries(PropertyStore.DefaultValues).forEach(([prop, value]) => - this.propertySet(prop, value)); - } - - getChildrenIds() { - return this._children_ids.concat(); // clone it! - } - - addChild(pos, childId) { - this._children_ids.splice(pos, 0, childId); - this.emit('child-added', this._client.getItem(childId), pos); - } - - removeChild(childId) { - // find it - let pos = -1; - for (let i = 0; i < this._children_ids.length; ++i) { - if (this._children_ids[i] === childId) { - pos = i; - break; - } - } - - if (pos < 0) { - Util.Logger.critical("Trying to remove child which doesn't exist"); - } else { - this._children_ids.splice(pos, 1); - this.emit('child-removed', this._client.getItem(childId)); - } - } - - moveChild(childId, newPos) { - // find the old position - let oldPos = -1; - for (let i = 0; i < this._children_ids.length; ++i) { - if (this._children_ids[i] === childId) { - oldPos = i; - break; - } - } - - if (oldPos < 0) { - Util.Logger.critical("tried to move child which wasn't in the list"); - return; - } - - if (oldPos !== newPos) { - this._children_ids.splice(oldPos, 1); - this._children_ids.splice(newPos, 0, childId); - this.emit('child-moved', oldPos, newPos, this._client.getItem(childId)); - } - } - - getChildren() { - return this._children_ids.map(el => this._client.getItem(el)); - } - - handleEvent(event, data, timestamp) { - if (!data) - data = GLib.Variant.new_int32(0); - - this._client.sendEvent(this._id, event, data, timestamp); - } - - getId() { - return this._id; - } - - sendAboutToShow() { - this._client.sendAboutToShow(this._id); - } -} - - -/** - * The client does the heavy lifting of actually reading layouts and distributing events - */ - -export const DBusClient = GObject.registerClass({ - Signals: {'ready-changed': {}}, -}, class AppIndicatorsDBusClient extends DBusProxy { - static get interfaceInfo() { - if (!this._interfaceInfo) { - this._interfaceInfo = Gio.DBusInterfaceInfo.new_for_xml( - DBusInterfaces.DBusMenu); - } - return this._interfaceInfo; - } - - static get baseItems() { - if (!this._baseItems) { - this._baseItems = { - 'children-display': GLib.Variant.new_string('submenu'), - }; - } - return this._baseItems; - } - - static destroy() { - delete this._interfaceInfo; - } - - _init(busName, objectPath) { - const {interfaceInfo} = AppIndicatorsDBusClient; - - super._init(busName, objectPath, interfaceInfo, - Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES); - - this._items = new Map(); - this._items.set(0, new DbusMenuItem(this, 0, DBusClient.baseItems, [])); - this._flagItemsUpdateRequired = false; - - // will be set to true if a layout update is needed once active - this._flagLayoutUpdateRequired = false; - - // property requests are queued - this._propertiesRequestedFor = new Set(/* ids */); - - this._layoutUpdated = false; - this._active = false; - } - - async initAsync(cancellable) { - await super.initAsync(cancellable); - - this._requestLayoutUpdate(); - } - - _onNameOwnerChanged() { - if (this.isReady) - this._requestLayoutUpdate(); - } - - get isReady() { - return this._layoutUpdated && !!this.gNameOwner; - } - - get cancellable() { - return this._cancellable; - } - - getRoot() { - return this._items.get(0); - } - - _requestLayoutUpdate() { - const cancellable = new Util.CancellableChild(this._cancellable); - this._beginLayoutUpdate(cancellable); - } - - async _requestProperties(propertyId, cancellable) { - this._propertiesRequestedFor.add(propertyId); - - if (this._propertiesRequest && this._propertiesRequest.pending()) - return; - - // if we don't have any requests queued, we'll need to add one - this._propertiesRequest = new PromiseUtils.IdlePromise( - GLib.PRIORITY_DEFAULT_IDLE, cancellable); - await this._propertiesRequest; - - const requestedProperties = Array.from(this._propertiesRequestedFor); - this._propertiesRequestedFor.clear(); - const [result] = await this.GetGroupPropertiesAsync(requestedProperties, - [], cancellable); - - result.forEach(([id, properties]) => { - const item = this._items.get(id); - if (!item) - return; - - item.resetProperties(); - - for (const [prop, value] of Object.entries(properties)) - item.propertySet(prop, value); - }); - } - - // Traverses the list of cached menu items and removes everyone that is not in the list - // so we don't keep alive unused items - _gcItems() { - const tag = new Date().getTime(); - - const toTraverse = [0]; - while (toTraverse.length > 0) { - const item = this.getItem(toTraverse.shift()); - item._dbusClientGcTag = tag; - Array.prototype.push.apply(toTraverse, item.getChildrenIds()); - } - - this._items.forEach((i, id) => { - if (i._dbusClientGcTag !== tag) - this._items.delete(id); - }); - } - - // the original implementation will only request partial layouts if somehow possible - // we try to save us from multiple kinds of race conditions by always requesting a full layout - _beginLayoutUpdate(cancellable) { - this._layoutUpdateUpdateAsync(cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - // the original implementation will only request partial layouts if somehow possible - // we try to save us from multiple kinds of race conditions by always requesting a full layout - async _layoutUpdateUpdateAsync(cancellable) { - // we only read the type property, because if the type changes after reading all properties, - // the view would have to replace the item completely which we try to avoid - if (this._layoutUpdateCancellable) - this._layoutUpdateCancellable.cancel(); - - this._layoutUpdateCancellable = cancellable; - - try { - const [revision_, root] = await this.GetLayoutAsync(0, -1, - ['type', 'children-display'], cancellable); - - this._updateLayoutState(true); - this._doLayoutUpdate(root, cancellable); - this._gcItems(); - this._flagLayoutUpdateRequired = false; - this._flagItemsUpdateRequired = false; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - this._updateLayoutState(false); - throw e; - } finally { - if (this._layoutUpdateCancellable === cancellable) - this._layoutUpdateCancellable = null; - } - } - - _updateLayoutState(state) { - const wasReady = this.isReady; - this._layoutUpdated = state; - if (this.isReady !== wasReady) - this.emit('ready-changed'); - } - - _doLayoutUpdate(item, cancellable) { - const [id, properties, children] = item; - - const childrenUnpacked = children.map(c => c.deep_unpack()); - const childrenIds = childrenUnpacked.map(([c]) => c); - - // make sure all our children exist - childrenUnpacked.forEach(c => this._doLayoutUpdate(c, cancellable)); - - // make sure we exist - const menuItem = this._items.get(id); - - if (menuItem) { - // we do, update our properties if necessary - for (const [prop, value] of Object.entries(properties)) - menuItem.propertySet(prop, value); - - // make sure our children are all at the right place, and exist - const oldChildrenIds = menuItem.getChildrenIds(); - for (let i = 0; i < childrenIds.length; ++i) { - // try to recycle an old child - let oldChild = -1; - for (let j = 0; j < oldChildrenIds.length; ++j) { - if (oldChildrenIds[j] === childrenIds[i]) { - [oldChild] = oldChildrenIds.splice(j, 1); - break; - } - } - - if (oldChild < 0) { - // no old child found, so create a new one! - menuItem.addChild(i, childrenIds[i]); - } else { - // old child found, reuse it! - menuItem.moveChild(childrenIds[i], i); - } - } - - // remove any old children that weren't reused - oldChildrenIds.forEach(c => menuItem.removeChild(c)); - - if (!this._flagItemsUpdateRequired) - return id; - } - - // we don't, so let's create us - let newMenuItem = menuItem; - - if (!newMenuItem) { - newMenuItem = new DbusMenuItem(this, id, properties, childrenIds); - this._items.set(id, newMenuItem); - } - - this._requestProperties(id, cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.warn(`Could not get menu properties menu proxy: ${e}`); - }); - - return id; - } - - async _doPropertiesUpdateAsync(cancellable) { - if (this._propertiesUpdateCancellable) - this._propertiesUpdateCancellable.cancel(); - - this._propertiesUpdateCancellable = cancellable; - - try { - const requests = []; - - this._items.forEach((_, id) => - requests.push(this._requestProperties(id, cancellable))); - - await Promise.all(requests); - } finally { - if (this._propertiesUpdateCancellable === cancellable) - this._propertiesUpdateCancellable = null; - } - } - - _doPropertiesUpdate() { - const cancellable = new Util.CancellableChild(this._cancellable); - this._doPropertiesUpdateAsync(cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - Util.Logger.warn(`Could not get menu properties menu proxy: ${e}`); - }); - } - - - set active(active) { - const wasActive = this._active; - this._active = active; - - if (active && wasActive !== active) { - if (this._flagLayoutUpdateRequired) { - this._requestLayoutUpdate(); - } else if (this._flagItemsUpdateRequired) { - this._doPropertiesUpdate(); - this._flagItemsUpdateRequired = false; - } - } - } - - _onSignal(_sender, signal, params) { - if (signal === 'LayoutUpdated') { - if (!this._active) { - this._flagLayoutUpdateRequired = true; - return; - } - - this._requestLayoutUpdate(); - } else if (signal === 'ItemsPropertiesUpdated') { - if (!this._active) { - this._flagItemsUpdateRequired = true; - return; - } - - this._onPropertiesUpdated(params.deep_unpack()); - } - } - - getItem(id) { - const item = this._items.get(id); - if (!item) - Util.Logger.warn(`trying to retrieve item for non-existing id ${id} !?`); - return item || null; - } - - // we don't need to cache and burst-send that since it will not happen that frequently - async sendAboutToShow(id) { - if (this._hasAboutToShow === false) - return; - - /* Some indicators (you, dropbox!) don't use the right signature - * and don't return a boolean, so we need to support both cases */ - try { - const ret = await this.gConnection.call(this.gName, this.gObjectPath, - this.gInterfaceName, 'AboutToShow', new GLib.Variant('(i)', [id]), - null, Gio.DBusCallFlags.NONE, -1, this._cancellable); - - if ((ret.is_of_type(new GLib.VariantType('(b)')) && - ret.get_child_value(0).get_boolean()) || - ret.is_of_type(new GLib.VariantType('()'))) - this._requestLayoutUpdate(); - } catch (e) { - if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD) || - e.matches(Gio.DBusError, Gio.DBusError.FAILED)) { - this._hasAboutToShow = false; - return; - } - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - - sendEvent(id, event, params, timestamp) { - if (!this.gNameOwner) - return; - - this.EventAsync(id, event, params, timestamp, this._cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - } - - _onPropertiesUpdated([changed, removed]) { - changed.forEach(([id, props]) => { - const item = this._items.get(id); - if (!item) - return; - - for (const [prop, value] of Object.entries(props)) - item.propertySet(prop, value); - }); - removed.forEach(([id, propNames]) => { - const item = this._items.get(id); - if (!item) - return; - - propNames.forEach(propName => item.propertySet(propName, null)); - }); - } -}); - -// //////////////////////////////////////////////////////////////////////// -// PART TWO: "View" frontend implementation. -// //////////////////////////////////////////////////////////////////////// - -// https://bugzilla.gnome.org/show_bug.cgi?id=731514 -// GNOME 3.10 and 3.12 can't open a nested submenu. -// Patches have been written, but it's not clear when (if?) they will be applied. -// We also don't know whether they will be backported to 3.10, so we will work around -// it in the meantime. Offending versions can be clearly identified: -const NEED_NESTED_SUBMENU_FIX = '_setOpenedSubMenu' in PopupMenu.PopupMenu.prototype; - -/** - * Creates new wrapper menu items and injects methods for managing them at runtime. - * - * Many functions in this object will be bound to the created item and executed as event - * handlers, so any `this` will refer to a menu item create in createItem - */ -const MenuItemFactory = { - createItem(client, dbusItem) { - // first, decide whether it's a submenu or not - let shellItem; - if (dbusItem.propertyGet('children-display') === 'submenu') - shellItem = new PopupMenu.PopupSubMenuMenuItem('FIXME'); - else if (dbusItem.propertyGet('type') === 'separator') - shellItem = new PopupMenu.PopupSeparatorMenuItem(''); - else - shellItem = new PopupMenu.PopupMenuItem('FIXME'); - - shellItem._dbusItem = dbusItem; - shellItem._dbusClient = client; - - if (shellItem instanceof PopupMenu.PopupMenuItem) { - shellItem._icon = new St.Icon({ - style_class: 'popup-menu-icon', - xAlign: Clutter.ActorAlign.END, - }); - shellItem.add_child(shellItem._icon); - shellItem.label.x_expand = true; - } - - // initialize our state - MenuItemFactory._updateLabel.call(shellItem); - MenuItemFactory._updateOrnament.call(shellItem); - MenuItemFactory._updateImage.call(shellItem); - MenuItemFactory._updateVisible.call(shellItem); - MenuItemFactory._updateSensitive.call(shellItem); - - // initially create children - if (shellItem instanceof PopupMenu.PopupSubMenuMenuItem) { - dbusItem.getChildren().forEach(c => - shellItem.menu.addMenuItem(MenuItemFactory.createItem(client, c))); - } - - // now, connect various events - Util.connectSmart(dbusItem, 'property-changed', - shellItem, MenuItemFactory._onPropertyChanged); - Util.connectSmart(dbusItem, 'child-added', - shellItem, MenuItemFactory._onChildAdded); - Util.connectSmart(dbusItem, 'child-removed', - shellItem, MenuItemFactory._onChildRemoved); - Util.connectSmart(dbusItem, 'child-moved', - shellItem, MenuItemFactory._onChildMoved); - Util.connectSmart(shellItem, 'activate', - shellItem, MenuItemFactory._onActivate); - - shellItem.connect('destroy', () => { - shellItem._dbusItem = null; - shellItem._dbusClient = null; - shellItem._icon = null; - }); - - if (shellItem.menu) { - Util.connectSmart(shellItem.menu, 'open-state-changed', - shellItem, MenuItemFactory._onOpenStateChanged); - } - - return shellItem; - }, - - _onOpenStateChanged(menu, open) { - if (open) { - if (NEED_NESTED_SUBMENU_FIX) { - // close our own submenus - if (menu._openedSubMenu) - menu._openedSubMenu.close(false); - - // register ourselves and close sibling submenus - if (menu._parent._openedSubMenu && menu._parent._openedSubMenu !== menu) - menu._parent._openedSubMenu.close(true); - - menu._parent._openedSubMenu = menu; - } - - this._dbusItem.handleEvent('opened', null, 0); - this._dbusItem.sendAboutToShow(); - } else { - if (NEED_NESTED_SUBMENU_FIX) { - // close our own submenus - if (menu._openedSubMenu) - menu._openedSubMenu.close(false); - } - - this._dbusItem.handleEvent('closed', null, 0); - } - }, - - _onActivate(_item, event) { - const timestamp = event.get_time(); - if (timestamp && this._dbusClient.indicator) - this._dbusClient.indicator.provideActivationToken(timestamp); - - this._dbusItem.handleEvent('clicked', GLib.Variant.new('i', 0), - timestamp); - }, - - _onPropertyChanged(dbusItem, prop, _value) { - if (prop === 'toggle-type' || prop === 'toggle-state') - MenuItemFactory._updateOrnament.call(this); - else if (prop === 'label') - MenuItemFactory._updateLabel.call(this); - else if (prop === 'enabled') - MenuItemFactory._updateSensitive.call(this); - else if (prop === 'visible') - MenuItemFactory._updateVisible.call(this); - else if (prop === 'icon-name' || prop === 'icon-data') - MenuItemFactory._updateImage.call(this); - else if (prop === 'type' || prop === 'children-display') - MenuItemFactory._replaceSelf.call(this); - else - Util.Logger.debug(`Unhandled property change: ${prop}`); - }, - - _onChildAdded(dbusItem, child, position) { - if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { - Util.Logger.warn('Tried to add a child to non-submenu item. Better recreate it as whole'); - MenuItemFactory._replaceSelf.call(this); - } else { - this.menu.addMenuItem(MenuItemFactory.createItem(this._dbusClient, child), position); - } - }, - - _onChildRemoved(dbusItem, child) { - if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { - Util.Logger.warn('Tried to remove a child from non-submenu item. Better recreate it as whole'); - MenuItemFactory._replaceSelf.call(this); - } else { - // find it! - this.menu._getMenuItems().forEach(item => { - if (item._dbusItem === child) - item.destroy(); - }); - } - }, - - _onChildMoved(dbusItem, child, oldpos, newpos) { - if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { - Util.Logger.warn('Tried to move a child in non-submenu item. Better recreate it as whole'); - MenuItemFactory._replaceSelf.call(this); - } else { - MenuUtils.moveItemInMenu(this.menu, child, newpos); - } - }, - - _updateLabel() { - const label = this._dbusItem.propertyGet('label').replace(/_([^_])/, '$1'); - - if (this.label) // especially on GS3.8, the separator item might not even have a hidden label - this.label.set_text(label); - }, - - _updateOrnament() { - if (!this.setOrnament) - return; // separators and alike might not have gotten the polyfill - - if (this._dbusItem.propertyGet('toggle-type') === 'checkmark' && - this._dbusItem.propertyGetInt('toggle-state')) - this.setOrnament(PopupMenu.Ornament.CHECK); - else if (this._dbusItem.propertyGet('toggle-type') === 'radio' && - this._dbusItem.propertyGetInt('toggle-state')) - this.setOrnament(PopupMenu.Ornament.DOT); - else - this.setOrnament(PopupMenu.Ornament.NONE); - }, - - async _updateImage() { - if (!this._icon) - return; // might be missing on submenus / separators - - const iconName = this._dbusItem.propertyGet('icon-name'); - const iconData = this._dbusItem.propertyGetVariant('icon-data'); - if (iconName) { - this._icon.icon_name = iconName; - } else if (iconData) { - try { - const inputStream = Gio.MemoryInputStream.new_from_bytes( - iconData.get_data_as_bytes()); - this._icon.gicon = await GdkPixbuf.Pixbuf.new_from_stream_async( - inputStream, this._dbusClient.cancellable); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - }, - - _updateVisible() { - this.visible = this._dbusItem.propertyGetBool('visible'); - }, - - _updateSensitive() { - this.setSensitive(this._dbusItem.propertyGetBool('enabled')); - }, - - _replaceSelf(newSelf) { - // create our new self if needed - if (!newSelf) - newSelf = MenuItemFactory.createItem(this._dbusClient, this._dbusItem); - - // first, we need to find our old position - let pos = -1; - const family = this._parent._getMenuItems(); - for (let i = 0; i < family.length; ++i) { - if (family[i] === this) - pos = i; - } - - if (pos < 0) - throw new Error("DBusMenu: can't replace non existing menu item"); - - - // add our new self while we're still alive - this._parent.addMenuItem(newSelf, pos); - - // now destroy our old self - this.destroy(); - }, -}; - -/** - * Utility functions not necessarily belonging into the item factory - */ -const MenuUtils = { - moveItemInMenu(menu, dbusItem, newpos) { - // HACK: we're really getting into the internals of the PopupMenu implementation - - // First, find our wrapper. Children tend to lie. We do not trust the old positioning. - const family = menu._getMenuItems(); - for (let i = 0; i < family.length; ++i) { - if (family[i]._dbusItem === dbusItem) { - // now, remove it - menu.box.remove_child(family[i]); - - // and add it again somewhere else - if (newpos < family.length && family[newpos] !== family[i]) - menu.box.insert_child_below(family[i], family[newpos]); - else - menu.box.add(family[i]); - - // skip the rest - return; - } - } - }, -}; - - -/** - * Processes DBus events, creates the menu items and handles the actions - * - * Something like a mini-god-object - */ -export class Client extends Signals.EventEmitter { - constructor(busName, path, indicator) { - super(); - - this._busName = busName; - this._busPath = path; - this._client = new DBusClient(busName, path); - this._rootMenu = null; // the shell menu - this._rootItem = null; // the DbusMenuItem for the root - this.indicator = indicator; - this.cancellable = new Util.CancellableChild(this.indicator.cancellable); - - this._client.initAsync(this.cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); - - Util.connectSmart(this._client, 'ready-changed', this, - () => this.emit('ready-changed')); - } - - get isReady() { - return this._client.isReady; - } - - // this will attach the client to an already existing menu that will be used as the root menu. - // it will also connect the client to be automatically destroyed when the menu dies. - attachToMenu(menu) { - this._rootMenu = menu; - this._rootItem = this._client.getRoot(); - this._itemsBeingAdded = new Set(); - - // cleanup: remove existing children (just in case) - this._rootMenu.removeAll(); - - if (NEED_NESTED_SUBMENU_FIX) - menu._setOpenedSubMenu = this._setOpenedSubmenu.bind(this); - - // connect handlers - Util.connectSmart(menu, 'open-state-changed', this, this._onMenuOpened); - Util.connectSmart(menu, 'destroy', this, this.destroy); - - Util.connectSmart(this._rootItem, 'child-added', this, this._onRootChildAdded); - Util.connectSmart(this._rootItem, 'child-removed', this, this._onRootChildRemoved); - Util.connectSmart(this._rootItem, 'child-moved', this, this._onRootChildMoved); - - // Dropbox requires us to call AboutToShow(0) first - this._rootItem.sendAboutToShow(); - - // fill the menu for the first time - const children = this._rootItem.getChildren(); - children.forEach(child => - this._onRootChildAdded(this._rootItem, child)); - } - - _setOpenedSubmenu(submenu) { - if (!submenu) - return; - - if (submenu._parent !== this._rootMenu) - return; - - if (submenu === this._openedSubMenu) - return; - - if (this._openedSubMenu && this._openedSubMenu.isOpen) - this._openedSubMenu.close(true); - - this._openedSubMenu = submenu; - } - - _onRootChildAdded(dbusItem, child, position) { - // Menu additions can be expensive, so let's do it in different chunks - const basePriority = this.isOpen ? GLib.PRIORITY_DEFAULT : GLib.PRIORITY_LOW; - const idlePromise = new PromiseUtils.IdlePromise( - basePriority + this._itemsBeingAdded.size, this.cancellable); - this._itemsBeingAdded.add(child); - - idlePromise.then(() => { - if (!this._itemsBeingAdded.has(child)) - return; - - this._rootMenu.addMenuItem( - MenuItemFactory.createItem(this, child), position); - }).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }).finally(() => this._itemsBeingAdded.delete(child)); - } - - _onRootChildRemoved(dbusItem, child) { - // children like to play hide and seek - // but we know how to find it for sure! - const item = this._rootMenu._getMenuItems().find(it => - it._dbusItem === child); - - if (item) - item.destroy(); - else - this._itemsBeingAdded.delete(child); - } - - _onRootChildMoved(dbusItem, child, oldpos, newpos) { - MenuUtils.moveItemInMenu(this._rootMenu, dbusItem, newpos); - } - - _onMenuOpened(menu, state) { - if (!this._rootItem) - return; - - this._client.active = state; - - if (state) { - if (this._openedSubMenu && this._openedSubMenu.isOpen) - this._openedSubMenu.close(); - - this._rootItem.handleEvent('opened', null, 0); - this._rootItem.sendAboutToShow(); - } else { - this._rootItem.handleEvent('closed', null, 0); - } - } - - destroy() { - this.emit('destroy'); - - if (this._client) - this._client.destroy(); - - this._client = null; - this._rootItem = null; - this._rootMenu = null; - this.indicator = null; - this._itemsBeingAdded = null; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js deleted file mode 100755 index edf16fc3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js +++ /dev/null @@ -1,103 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import {CancellableChild, Logger} from './util.js'; - -Gio._promisify(Gio.DBusProxy.prototype, 'init_async'); - -export const DBusProxy = GObject.registerClass({ - Signals: {'destroy': {}}, -}, class DBusProxy extends Gio.DBusProxy { - static get TUPLE_VARIANT_TYPE() { - if (!this._tupleVariantType) - this._tupleVariantType = new GLib.VariantType('(v)'); - - return this._tupleVariantType; - } - - static destroy() { - delete this._tupleType; - } - - _init(busName, objectPath, interfaceInfo, flags = Gio.DBusProxyFlags.NONE) { - if (interfaceInfo.signals.length) - Logger.warn('Avoid exposing signals to gjs!'); - - super._init({ - gConnection: Gio.DBus.session, - gInterfaceName: interfaceInfo.name, - gInterfaceInfo: interfaceInfo, - gName: busName, - gObjectPath: objectPath, - gFlags: flags, - }); - - this._signalIds = []; - - if (!(flags & Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS)) { - this._signalIds.push(this.connect('g-signal', - (_proxy, ...args) => this._onSignal(...args))); - } - - this._signalIds.push(this.connect('notify::g-name-owner', () => - this._onNameOwnerChanged())); - } - - async initAsync(cancellable) { - cancellable = new CancellableChild(cancellable); - await this.init_async(GLib.PRIORITY_DEFAULT, cancellable); - this._cancellable = cancellable; - - this.gInterfaceInfo.methods.map(m => m.name).forEach(method => - this._ensureAsyncMethod(method)); - } - - destroy() { - this.emit('destroy'); - - this._signalIds.forEach(id => this.disconnect(id)); - - if (this._cancellable) - this._cancellable.cancel(); - } - - // This can be removed when we will have GNOME 43 as minimum version - _ensureAsyncMethod(method) { - if (this[`${method}Async`]) - return; - - if (!this[`${method}Remote`]) - throw new Error(`Missing remote method '${method}'`); - - this[`${method}Async`] = function (...args) { - return new Promise((resolve, reject) => { - this[`${method}Remote`](...args, (ret, e) => { - if (e) - reject(e); - else - resolve(ret); - }); - }); - }; - } - - _onSignal() { - } - - getProperty(propertyName, cancellable) { - return this.gConnection.call(this.gName, - this.gObjectPath, 'org.freedesktop.DBus.Properties', 'Get', - GLib.Variant.new('(ss)', [this.gInterfaceName, propertyName]), - DBusProxy.TUPLE_VARIANT_TYPE, Gio.DBusCallFlags.NONE, -1, - cancellable); - } - - getProperties(cancellable) { - return this.gConnection.call(this.gName, - this.gObjectPath, 'org.freedesktop.DBus.Properties', 'GetAll', - GLib.Variant.new('(s)', [this.gInterfaceName]), - GLib.VariantType.new('(a{sv})'), Gio.DBusCallFlags.NONE, -1, - cancellable); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js deleted file mode 100755 index 6f69aa18..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js +++ /dev/null @@ -1,89 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import * as Extension from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as StatusNotifierWatcher from './statusNotifierWatcher.js'; -import * as Interfaces from './interfaces.js'; -import * as TrayIconsManager from './trayIconsManager.js'; -import * as Util from './util.js'; -import {SettingsManager} from './settingsManager.js'; - -export default class AppIndicatorExtension extends Extension.Extension { - constructor(...args) { - super(...args); - - Util.Logger.init(this); - Interfaces.initialize(this); - - this._isEnabled = false; - this._statusNotifierWatcher = null; - this._watchDog = new Util.NameWatcher(StatusNotifierWatcher.WATCHER_BUS_NAME); - this._watchDog.connect('vanished', () => this._maybeEnableAfterNameAvailable()); - - // HACK: we want to leave the watchdog alive when disabling the extension, - // but if we are being reloaded, we destroy it since it could be considered - // a leak and spams our log, too. - /* eslint-disable no-undef */ - if (typeof global['--appindicator-extension-on-reload'] === 'function') - global['--appindicator-extension-on-reload'](); - - global['--appindicator-extension-on-reload'] = () => { - Util.Logger.debug('Reload detected, destroying old watchdog'); - this._watchDog.destroy(); - this._watchDog = null; - }; - /* eslint-enable no-undef */ - } - - enable() { - this._isEnabled = true; - SettingsManager.initialize(this); - Util.tryCleanupOldIndicators(); - this._maybeEnableAfterNameAvailable(); - TrayIconsManager.TrayIconsManager.initialize(); - } - - disable() { - this._isEnabled = false; - TrayIconsManager.TrayIconsManager.destroy(); - - if (this._statusNotifierWatcher !== null) { - this._statusNotifierWatcher.destroy(); - this._statusNotifierWatcher = null; - } - - SettingsManager.destroy(); - } - - // FIXME: when entering/leaving the lock screen, the extension might be - // enabled/disabled rapidly. - // This will create very bad side effects in case we were not done unowning - // the name while trying to own it again. Since g_bus_unown_name doesn't - // fire any callback when it's done, we need to monitor the bus manually - // to find out when the name vanished so we can reclaim it again. - _maybeEnableAfterNameAvailable() { - // by the time we get called whe might not be enabled - if (!this._isEnabled || this._statusNotifierWatcher) - return; - - if (this._watchDog.nameAcquired && this._watchDog.nameOnBus) - return; - - this._statusNotifierWatcher = new StatusNotifierWatcher.StatusNotifierWatcher( - this._watchDog); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js deleted file mode 100755 index 36101843..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/iconCache.js +++ /dev/null @@ -1,179 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; - -import * as PromiseUtils from './promiseUtils.js'; -import * as Util from './util.js'; - -// The icon cache caches icon objects in case they're reused shortly aftwerwards. -// This is necessary for some indicators like skype which rapidly switch between serveral icons. -// Without caching, the garbage collection would never be able to handle the amount of new icon data. -// If the lifetime of an icon is over, the cache will destroy the icon. (!) -// The presence of active icons will extend the lifetime. - -const GC_INTERVAL = 100; // seconds -const LIFETIME_TIMESPAN = 120; // seconds - -// how to use: see IconCache.add, IconCache.get -export class IconCache { - constructor() { - this._cache = new Map(); - this._activeIcons = Object.create(null); - this._lifetime = new Map(); // we don't want to attach lifetime to the object - } - - add(id, icon) { - if (!(icon instanceof Gio.Icon)) { - Util.Logger.critical('IconCache: Only Gio.Icons are supported'); - return null; - } - - if (!id) { - Util.Logger.critical('IconCache: Invalid ID provided'); - return null; - } - - const oldIcon = this._cache.get(id); - if (!oldIcon || !oldIcon.equal(icon)) { - Util.Logger.debug(`IconCache: adding ${id}: ${icon}`); - this._cache.set(id, icon); - } else { - icon = oldIcon; - } - - this._renewLifetime(id); - this._checkGC(); - - return icon; - } - - updateActive(iconType, gicon, isActive) { - if (!gicon) - return; - - const previousActive = this._activeIcons[iconType]; - - if (isActive && [...this._cache.values()].some(icon => icon === gicon)) - this._activeIcons[iconType] = gicon; - else if (previousActive === gicon) - delete this._activeIcons[iconType]; - else - return; - - if (previousActive) { - this._cache.forEach((icon, id) => { - if (icon === previousActive) - this._renewLifetime(id); - }); - } - } - - _remove(id) { - Util.Logger.debug(`IconCache: removing ${id}`); - - this._cache.delete(id); - this._lifetime.delete(id); - } - - _renewLifetime(id) { - this._lifetime.set(id, new Date().getTime() + LIFETIME_TIMESPAN * 1000); - } - - forceDestroy(id) { - const gicon = this._cache.has(id); - if (gicon) { - Object.keys(this._activeIcons).forEach(iconType => - this.updateActive(iconType, gicon, false)); - this._remove(id); - this._checkGC(); - } - } - - // marks all the icons as removable, if something doesn't claim them before - weakClear() { - this._activeIcons = Object.create(null); - this._checkGC(); - } - - // removes everything from the cache - clear() { - this._activeIcons = Object.create(null); - this._cache.forEach((_icon, id) => this._remove(id)); - this._checkGC(); - } - - // returns an object from the cache, or null if it can't be found. - get(id) { - const icon = this._cache.get(id); - if (icon) { - Util.Logger.debug(`IconCache: retrieving ${id}: ${icon}`); - this._renewLifetime(id); - return icon; - } - - return null; - } - - async _checkGC() { - const cacheIsEmpty = this._cache.size === 0; - - if (!cacheIsEmpty && !this._gcTimeout) { - Util.Logger.debug('IconCache: garbage collector started'); - let anyUnusedInCache = false; - this._gcTimeout = new PromiseUtils.TimeoutSecondsPromise(GC_INTERVAL, - GLib.PRIORITY_LOW); - try { - await this._gcTimeout; - anyUnusedInCache = this._gc(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'IconCache: garbage collector'); - } finally { - delete this._gcTimeout; - } - - if (anyUnusedInCache) - this._checkGC(); - } else if (cacheIsEmpty && this._gcTimeout) { - Util.Logger.debug('IconCache: garbage collector stopped'); - this._gcTimeout.cancel(); - } - } - - _gc() { - const time = new Date().getTime(); - let anyUnused = false; - - this._cache.forEach((icon, id) => { - if (Object.values(this._activeIcons).includes(icon)) { - Util.Logger.debug(`IconCache: ${id} is in use.`); - } else if (this._lifetime.get(id) < time) { - this._remove(id); - } else { - anyUnused = true; - Util.Logger.debug(`IconCache: ${id} survived this round.`); - } - }); - - return anyUnused; - } - - destroy() { - this.clear(); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js deleted file mode 100755 index 49ecde81..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js +++ /dev/null @@ -1,585 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Panel from 'resource:///org/gnome/shell/ui/panel.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; - -import * as AppIndicator from './appIndicator.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as SettingsManager from './settingsManager.js'; -import * as Util from './util.js'; -import * as DBusMenu from './dbusMenu.js'; - -const DEFAULT_ICON_SIZE = Panel.PANEL_ICON_SIZE || 16; - -export function addIconToPanel(statusIcon) { - if (!(statusIcon instanceof BaseStatusIcon)) - throw TypeError(`Unexpected icon type: ${statusIcon}`); - - const settings = SettingsManager.getDefaultGSettings(); - const indicatorId = `appindicator-${statusIcon.uniqueId}`; - - const currentIcon = Main.panel.statusArea[indicatorId]; - if (currentIcon) { - if (currentIcon !== statusIcon) - currentIcon.destroy(); - - Main.panel.statusArea[indicatorId] = null; - } - - Main.panel.addToStatusArea(indicatorId, statusIcon, 1, - settings.get_string('tray-pos')); - - Util.connectSmart(settings, 'changed::tray-pos', statusIcon, () => - addIconToPanel(statusIcon)); -} - -export function getTrayIcons() { - return Object.values(Main.panel.statusArea).filter( - i => i instanceof IndicatorStatusTrayIcon); -} - -export function getAppIndicatorIcons() { - return Object.values(Main.panel.statusArea).filter( - i => i instanceof IndicatorStatusIcon); -} - -export const BaseStatusIcon = GObject.registerClass( -class IndicatorBaseStatusIcon extends PanelMenu.Button { - _init(menuAlignment, nameText, iconActor, dontCreateMenu) { - super._init(menuAlignment, nameText, dontCreateMenu); - - const settings = SettingsManager.getDefaultGSettings(); - Util.connectSmart(settings, 'changed::icon-opacity', this, this._updateOpacity); - this.connect('notify::hover', () => this._onHoverChanged()); - - if (!super._onDestroy) - this.connect('destroy', () => this._onDestroy()); - - this._box = new St.BoxLayout({style_class: 'panel-status-indicators-box'}); - this.add_child(this._box); - - this._setIconActor(iconActor); - this._showIfReady(); - } - - _setIconActor(icon) { - if (!(icon instanceof Clutter.Actor)) - throw new Error(`${icon} is not a valid actor`); - - if (this._icon && this._icon !== icon) - this._icon.destroy(); - - this._icon = icon; - this._updateEffects(); - this._monitorIconEffects(); - - if (this._icon) { - this._box.add_child(this._icon); - const id = this._icon.connect('destroy', () => { - this._icon.disconnect(id); - this._icon = null; - this._monitorIconEffects(); - }); - } - } - - _onDestroy() { - if (this._icon) - this._icon.destroy(); - - if (super._onDestroy) - super._onDestroy(); - } - - isReady() { - throw new GObject.NotImplementedError('isReady() in %s'.format(this.constructor.name)); - } - - get icon() { - return this._icon; - } - - get uniqueId() { - throw new GObject.NotImplementedError('uniqueId in %s'.format(this.constructor.name)); - } - - _showIfReady() { - this.visible = this.isReady(); - } - - _onHoverChanged() { - if (this.hover) { - this.opacity = 255; - if (this._icon) - this._icon.remove_effect_by_name('desaturate'); - } else { - this._updateEffects(); - } - } - - _updateOpacity() { - const settings = SettingsManager.getDefaultGSettings(); - const userValue = settings.get_user_value('icon-opacity'); - if (userValue) - this.opacity = userValue.unpack(); - else - this.opacity = 255; - } - - _updateEffects() { - this._updateOpacity(); - - if (this._icon) { - this._updateSaturation(); - this._updateBrightnessContrast(); - } - } - - _monitorIconEffects() { - const settings = SettingsManager.getDefaultGSettings(); - const monitoring = !!this._iconSaturationIds; - - if (!this._icon && monitoring) { - Util.disconnectSmart(settings, this, this._iconSaturationIds); - delete this._iconSaturationIds; - - Util.disconnectSmart(settings, this, this._iconBrightnessIds); - delete this._iconBrightnessIds; - - Util.disconnectSmart(settings, this, this._iconContrastIds); - delete this._iconContrastIds; - } else if (this._icon && !monitoring) { - this._iconSaturationIds = - Util.connectSmart(settings, 'changed::icon-saturation', this, - this._updateSaturation); - this._iconBrightnessIds = - Util.connectSmart(settings, 'changed::icon-brightness', this, - this._updateBrightnessContrast); - this._iconContrastIds = - Util.connectSmart(settings, 'changed::icon-contrast', this, - this._updateBrightnessContrast); - } - } - - _updateSaturation() { - const settings = SettingsManager.getDefaultGSettings(); - const desaturationValue = settings.get_double('icon-saturation'); - let desaturateEffect = this._icon.get_effect('desaturate'); - - if (desaturationValue > 0) { - if (!desaturateEffect) { - desaturateEffect = new Clutter.DesaturateEffect(); - this._icon.add_effect_with_name('desaturate', desaturateEffect); - } - desaturateEffect.set_factor(desaturationValue); - } else if (desaturateEffect) { - this._icon.remove_effect(desaturateEffect); - } - } - - _updateBrightnessContrast() { - const settings = SettingsManager.getDefaultGSettings(); - const brightnessValue = settings.get_double('icon-brightness'); - const contrastValue = settings.get_double('icon-contrast'); - let brightnessContrastEffect = this._icon.get_effect('brightness-contrast'); - - if (brightnessValue !== 0 | contrastValue !== 0) { - if (!brightnessContrastEffect) { - brightnessContrastEffect = new Clutter.BrightnessContrastEffect(); - this._icon.add_effect_with_name('brightness-contrast', brightnessContrastEffect); - } - brightnessContrastEffect.set_brightness(brightnessValue); - brightnessContrastEffect.set_contrast(contrastValue); - } else if (brightnessContrastEffect) { - this._icon.remove_effect(brightnessContrastEffect); - } - } -}); - -/* - * IndicatorStatusIcon implements an icon in the system status area - */ -export const IndicatorStatusIcon = GObject.registerClass( -class IndicatorStatusIcon extends BaseStatusIcon { - _init(indicator) { - super._init(0.5, indicator.accessibleName, - new AppIndicator.IconActor(indicator, DEFAULT_ICON_SIZE)); - this._indicator = indicator; - - this._lastClickTime = -1; - this._lastClickX = -1; - this._lastClickY = -1; - - this._box.add_style_class_name('appindicator-box'); - - Util.connectSmart(this._indicator, 'ready', this, this._showIfReady); - Util.connectSmart(this._indicator, 'menu', this, this._updateMenu); - Util.connectSmart(this._indicator, 'label', this, this._updateLabel); - Util.connectSmart(this._indicator, 'status', this, this._updateStatus); - Util.connectSmart(this._indicator, 'reset', this, () => { - this._updateStatus(); - this._updateLabel(); - }); - Util.connectSmart(this._indicator, 'accessible-name', this, () => - this.set_accessible_name(this._indicator.accessibleName)); - Util.connectSmart(this._indicator, 'destroy', this, () => this.destroy()); - - this.connect('notify::visible', () => this._updateMenu()); - - this._showIfReady(); - } - - _onDestroy() { - if (this._menuClient) { - this._menuClient.disconnect(this._menuReadyId); - this._menuClient.destroy(); - this._menuClient = null; - } - - super._onDestroy(); - } - - get uniqueId() { - return this._indicator.uniqueId; - } - - isReady() { - return this._indicator && this._indicator.isReady; - } - - _updateLabel() { - const {label} = this._indicator; - if (label) { - if (!this._label || !this._labelBin) { - this._labelBin = new St.Bin({ - yAlign: Clutter.ActorAlign.CENTER, - }); - this._label = new St.Label(); - Util.addActor(this._labelBin, this._label); - Util.addActor(this._box, this._labelBin); - } - this._label.set_text(label); - if (!this._box.contains(this._labelBin)) - Util.addActor(this._box, this._labelBin); // FIXME: why is it suddenly necessary? - } else if (this._label) { - this._labelBin.destroy_all_children(); - Util.removeActor(this._box, this._labelBin); - this._labelBin.destroy(); - delete this._labelBin; - delete this._label; - } - } - - _updateStatus() { - const wasVisible = this.visible; - this.visible = this._indicator.status !== AppIndicator.SNIStatus.PASSIVE; - - if (this.visible !== wasVisible) - this._indicator.checkAlive().catch(logError); - } - - _updateMenu() { - if (this._menuClient) { - this._menuClient.disconnect(this._menuReadyId); - this._menuClient.destroy(); - this._menuClient = null; - this.menu.removeAll(); - } - - if (this.visible && this._indicator.menuPath) { - this._menuClient = new DBusMenu.Client(this._indicator.busName, - this._indicator.menuPath, this._indicator); - - if (this._menuClient.isReady) - this._menuClient.attachToMenu(this.menu); - - this._menuReadyId = this._menuClient.connect('ready-changed', () => { - if (this._menuClient.isReady) - this._menuClient.attachToMenu(this.menu); - else - this._updateMenu(); - }); - } - } - - _showIfReady() { - if (!this.isReady()) - return; - - this._updateLabel(); - this._updateStatus(); - this._updateMenu(); - } - - _updateClickCount(event) { - const [x, y] = event.get_coords(); - const time = event.get_time(); - const {doubleClickDistance, doubleClickTime} = - Clutter.Settings.get_default(); - - if (time > (this._lastClickTime + doubleClickTime) || - (Math.abs(x - this._lastClickX) > doubleClickDistance) || - (Math.abs(y - this._lastClickY) > doubleClickDistance)) - this._clickCount = 0; - - this._lastClickTime = time; - this._lastClickX = x; - this._lastClickY = y; - - this._clickCount = (this._clickCount % 2) + 1; - - return this._clickCount; - } - - _maybeHandleDoubleClick(event) { - if (this._indicator.supportsActivation === false) - return Clutter.EVENT_PROPAGATE; - - if (event.get_button() !== Clutter.BUTTON_PRIMARY) - return Clutter.EVENT_PROPAGATE; - - if (this._updateClickCount(event) === 2) { - this._indicator.open(...event.get_coords(), event.get_time()); - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } - - async _waitForDoubleClick() { - const {doubleClickTime} = Clutter.Settings.get_default(); - this._waitDoubleClickPromise = new PromiseUtils.TimeoutPromise( - doubleClickTime); - - try { - await this._waitDoubleClickPromise; - this.menu.toggle(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - throw e; - } finally { - delete this._waitDoubleClickPromise; - } - } - - vfunc_event(event) { - if (this.menu.numMenuItems && event.type() === Clutter.EventType.TOUCH_BEGIN) - this.menu.toggle(); - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_button_press_event(event) { - if (this._waitDoubleClickPromise) - this._waitDoubleClickPromise.cancel(); - - // if middle mouse button clicked send SecondaryActivate dbus event and do not show appindicator menu - if (event.get_button() === Clutter.BUTTON_MIDDLE) { - if (Main.panel.menuManager.activeMenu) - Main.panel.menuManager._closeMenu(true, Main.panel.menuManager.activeMenu); - this._indicator.secondaryActivate(event.get_time(), ...event.get_coords()); - return Clutter.EVENT_STOP; - } - - if (event.get_button() === Clutter.BUTTON_SECONDARY) { - this.menu.toggle(); - return Clutter.EVENT_PROPAGATE; - } - - const doubleClickHandled = this._maybeHandleDoubleClick(event); - if (doubleClickHandled === Clutter.EVENT_PROPAGATE && - event.get_button() === Clutter.BUTTON_PRIMARY && - this.menu.numMenuItems) { - if (this._indicator.supportsActivation !== false) - this._waitForDoubleClick().catch(logError); - else - this.menu.toggle(); - } - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_scroll_event(event) { - // Since Clutter 1.10, clutter will always send a smooth scrolling event - // with explicit deltas, no matter what input device is used - // In fact, for every scroll there will be a smooth and non-smooth scroll - // event, and we can choose which one we interpret. - if (event.get_scroll_direction() === Clutter.ScrollDirection.SMOOTH) { - const [dx, dy] = event.get_scroll_delta(); - - this._indicator.scroll(dx, dy); - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } -}); - -export const IndicatorStatusTrayIcon = GObject.registerClass( -class IndicatorTrayIcon extends BaseStatusIcon { - _init(icon) { - super._init(0.5, icon.wm_class, icon, {dontCreateMenu: true}); - Util.Logger.debug(`Adding legacy tray icon ${this.uniqueId}`); - this._box.add_style_class_name('appindicator-trayicons-box'); - this.add_style_class_name('appindicator-icon'); - this.add_style_class_name('tray-icon'); - - this.connect('button-press-event', (_actor, _event) => { - this.add_style_pseudo_class('active'); - return Clutter.EVENT_PROPAGATE; - }); - this.connect('button-release-event', (_actor, event) => { - this._icon.click(event); - this.remove_style_pseudo_class('active'); - return Clutter.EVENT_PROPAGATE; - }); - this.connect('key-press-event', (_actor, event) => { - this.add_style_pseudo_class('active'); - this._icon.click(event); - return Clutter.EVENT_PROPAGATE; - }); - this.connect('key-release-event', (_actor, event) => { - this._icon.click(event); - this.remove_style_pseudo_class('active'); - return Clutter.EVENT_PROPAGATE; - }); - - Util.connectSmart(this._icon, 'destroy', this, () => { - icon.clear_effects(); - this.destroy(); - }); - - const settings = SettingsManager.getDefaultGSettings(); - Util.connectSmart(settings, 'changed::icon-size', this, this._updateIconSize); - - const themeContext = St.ThemeContext.get_for_stage(global.stage); - Util.connectSmart(themeContext, 'notify::scale-factor', this, () => - this._updateIconSize()); - - this._updateIconSize(); - } - - _onDestroy() { - Util.Logger.debug(`Destroying legacy tray icon ${this.uniqueId}`); - - if (this._waitDoubleClickPromise) - this._waitDoubleClickPromise.cancel(); - - super._onDestroy(); - } - - isReady() { - return !!this._icon; - } - - get uniqueId() { - return `legacy:${this._icon.wm_class}:${this._icon.pid}`; - } - - vfunc_navigate_focus(from, direction) { - this.grab_key_focus(); - return super.vfunc_navigate_focus(from, direction); - } - - _getSimulatedButtonEvent(touchEvent) { - const event = Clutter.Event.new(Clutter.EventType.BUTTON_RELEASE); - event.set_button(1); - event.set_time(touchEvent.get_time()); - event.set_flags(touchEvent.get_flags()); - event.set_stage(global.stage); - event.set_source(touchEvent.get_source()); - event.set_coords(...touchEvent.get_coords()); - event.set_state(touchEvent.get_state()); - return event; - } - - vfunc_touch_event(event) { - // Under X11 we rely on emulated pointer events - if (!imports.gi.Meta.is_wayland_compositor()) - return Clutter.EVENT_PROPAGATE; - - const slot = event.get_event_sequence().get_slot(); - - if (!this._touchPressSlot && - event.get_type() === Clutter.EventType.TOUCH_BEGIN) { - this.add_style_pseudo_class('active'); - this._touchButtonEvent = this._getSimulatedButtonEvent(event); - this._touchPressSlot = slot; - this._touchDelayPromise = new PromiseUtils.TimeoutPromise( - AppDisplay.MENU_POPUP_TIMEOUT); - this._touchDelayPromise.then(() => { - delete this._touchDelayPromise; - delete this._touchPressSlot; - this._touchButtonEvent.set_button(3); - this._icon.click(this._touchButtonEvent); - this.remove_style_pseudo_class('active'); - }); - } else if (event.get_type() === Clutter.EventType.TOUCH_END && - this._touchPressSlot === slot) { - delete this._touchPressSlot; - delete this._touchButtonEvent; - if (this._touchDelayPromise) { - this._touchDelayPromise.cancel(); - delete this._touchDelayPromise; - } - - this._icon.click(this._getSimulatedButtonEvent(event)); - this.remove_style_pseudo_class('active'); - } else if (event.get_type() === Clutter.EventType.TOUCH_UPDATE && - this._touchPressSlot === slot) { - this.add_style_pseudo_class('active'); - this._touchButtonEvent = this._getSimulatedButtonEvent(event); - } - - return Clutter.EVENT_PROPAGATE; - } - - vfunc_leave_event(event) { - this.remove_style_pseudo_class('active'); - - if (this._touchDelayPromise) { - this._touchDelayPromise.cancel(); - delete this._touchDelayPromise; - } - - return super.vfunc_leave_event(event); - } - - _updateIconSize() { - const settings = SettingsManager.getDefaultGSettings(); - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - let iconSize = settings.get_int('icon-size'); - - if (iconSize <= 0) - iconSize = DEFAULT_ICON_SIZE; - - this.height = -1; - this._icon.set({ - width: iconSize * scaleFactor, - height: iconSize * scaleFactor, - xAlign: Clutter.ActorAlign.CENTER, - yAlign: Clutter.ActorAlign.CENTER, - }); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml deleted file mode 100755 index e98e04ec..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/DBusMenu.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml deleted file mode 100755 index 8c362944..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierItem.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml deleted file mode 100755 index e450d041..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces-xml/StatusNotifierWatcher.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js deleted file mode 100755 index 0a97907f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/interfaces.js +++ /dev/null @@ -1,52 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -export let StatusNotifierItem = null; -export let StatusNotifierWatcher = null; -export let DBusMenu = null; - -// loads a xml file into an in-memory string -function loadInterfaceXml(extension, filename) { - const interfacesDir = extension.dir.get_child('interfaces-xml'); - const file = interfacesDir.get_child(filename); - const [result, contents] = imports.gi.GLib.file_get_contents(file.get_path()); - - if (result) { - // HACK: The "" + trick is important as hell because file_get_contents returns - // an object (WTF?) but Gio.makeProxyWrapper requires `typeof() === "string"` - // Otherwise, it will try to check `instanceof XML` and fail miserably because there - // is no `XML` on very recent SpiderMonkey releases (or, if SpiderMonkey is old enough, - // will spit out a TypeError soon). - let nodeContents = contents; - if (contents instanceof Uint8Array) - nodeContents = imports.byteArray.toString(contents); - return `${nodeContents}`; - } else { - throw new Error(`AppIndicatorSupport: Could not load file: ${filename}`); - } -} - -export function initialize(extension) { - StatusNotifierItem = loadInterfaceXml(extension, 'StatusNotifierItem.xml'); - StatusNotifierWatcher = loadInterfaceXml(extension, 'StatusNotifierWatcher.xml'); - DBusMenu = loadInterfaceXml(extension, 'DBusMenu.xml'); -} - -export function destroy() { - StatusNotifierItem = null; - StatusNotifierWatcher = null; - DBusMenu = null; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/cs/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/cs/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index c66d72ef..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/cs/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/de/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/de/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 6edb4198..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/de/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/fr/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/fr/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index ba0d6671..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/fr/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/hu/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/hu/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index ffbe4ed1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/hu/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/it/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/it/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 1b009fd7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/it/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ja/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ja/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index d22309b6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ja/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ko/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ko/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 6d33af8d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ko/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/nl/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/nl/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 9d81088f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/nl/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/oc/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/oc/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index fe31bca0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/oc/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pl/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pl/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 4536d6e5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pl/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pt_BR/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pt_BR/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 0bb1b446..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/pt_BR/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ru/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ru/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 46e5781f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ru/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sk/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sk/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 060d9c3d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sk/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index a7770c59..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr@latin/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr@latin/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index af2179f9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/sr@latin/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ta/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ta/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 9b6e5a67..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/ta/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/tr/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/tr/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index d31e5f21..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/tr/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/uk/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/uk/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index 88c7fbcf..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/uk/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_CN/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_CN/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index df288443..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_CN/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_TW/LC_MESSAGES/AppIndicatorExtension.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_TW/LC_MESSAGES/AppIndicatorExtension.mo deleted file mode 100755 index f66fd67a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/locale/zh_TW/LC_MESSAGES/AppIndicatorExtension.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json deleted file mode 100755 index 968ccd45..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Adds AppIndicator, KStatusNotifierItem and legacy Tray icons support to the Shell", - "gettext-domain": "AppIndicatorExtension", - "name": "AppIndicator and KStatusNotifierItem Support", - "settings-schema": "org.gnome.shell.extensions.appindicator", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator", - "uuid": "appindicatorsupport@rgcjonas.gmail.com", - "version": 58 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js deleted file mode 100755 index ce4c3f3c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/pixmapsUtils.js +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -export function argbToRgba(src) { - const dest = new Uint8Array(src.length); - - for (let j = 0; j < src.length; j += 4) { - const srcAlpha = src[j]; - - dest[j] = src[j + 1]; /* red */ - dest[j + 1] = src[j + 2]; /* green */ - dest[j + 2] = src[j + 3]; /* blue */ - dest[j + 3] = srcAlpha; /* alpha */ - } - - return dest; -} - -export function getBestPixmap(pixmapsVariant, preferredSize) { - if (!pixmapsVariant) - throw new TypeError('null pixmapsVariant'); - - const pixmapsVariantsArray = new Array(pixmapsVariant.n_children()); - if (!pixmapsVariantsArray.length) - throw TypeError('Empty Icon found'); - - for (let i = 0; i < pixmapsVariantsArray.length; ++i) - pixmapsVariantsArray[i] = pixmapsVariant.get_child_value(i); - - const pixmapsSizedArray = pixmapsVariantsArray.map((pixmapVariant, index) => ({ - width: pixmapVariant.get_child_value(0).unpack(), - height: pixmapVariant.get_child_value(1).unpack(), - index, - })); - - const sortedIconPixmapArray = pixmapsSizedArray.sort( - ({width: widthA, height: heightA}, {width: widthB, height: heightB}) => { - const areaA = widthA * heightA; - const areaB = widthB * heightB; - - return areaA - areaB; - }); - - // we prefer any pixmap that is equal or bigger than our requested size - const qualifiedIconPixmapArray = sortedIconPixmapArray.filter(({width, height}) => - width >= preferredSize && height >= preferredSize); - - const {width, height, index} = qualifiedIconPixmapArray.length > 0 - ? qualifiedIconPixmapArray[0] : sortedIconPixmapArray.pop(); - - const pixmapVariant = pixmapsVariantsArray[index].get_child_value(2); - const rowStride = width * 4; // hopefully this is correct - - return {pixmapVariant, width, height, rowStride}; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js deleted file mode 100755 index 625bc104..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/prefs.js +++ /dev/null @@ -1,326 +0,0 @@ -// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- - -/* exported init, buildPrefsWidget */ - -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; - -import { - ExtensionPreferences, - gettext as _ -} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const AppIndicatorPreferences = GObject.registerClass( -class AppIndicatorPreferences extends Gtk.Box { - _init(extension) { - super._init({orientation: Gtk.Orientation.VERTICAL, spacing: 30}); - this._settings = extension.getSettings(); - - let label = null; - let widget = null; - - this.preferences_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 8, - margin_start: 30, - margin_end: 30, - margin_top: 30, - margin_bottom: 30, - }); - this.custom_icons_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - - label = new Gtk.Label({ - label: _('Enable Legacy Tray Icons support'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.Switch({halign: Gtk.Align.END}); - - this._settings.bind('legacy-tray-enabled', widget, 'active', - Gio.SettingsBindFlags.DEFAULT); - - this.legacy_tray_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - - this.legacy_tray_hbox.append(label); - this.legacy_tray_hbox.append(widget); - - // Icon opacity - this.opacity_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Opacity (min: 0, max: 255)'), - hexpand: true, - halign: Gtk.Align.START, - }); - - widget = new Gtk.SpinButton({halign: Gtk.Align.END}); - widget.set_sensitive(true); - widget.set_range(0, 255); - widget.set_value(this._settings.get_int('icon-opacity')); - widget.set_increments(1, 2); - widget.connect('value-changed', w => { - this._settings.set_int('icon-opacity', w.get_value_as_int()); - }); - this.opacity_hbox.append(label); - this.opacity_hbox.append(widget); - - // Icon saturation - this.saturation_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Desaturation (min: 0.0, max: 1.0)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1}); - widget.set_sensitive(true); - widget.set_range(0.0, 1.0); - widget.set_value(this._settings.get_double('icon-saturation')); - widget.set_increments(0.1, 0.2); - widget.connect('value-changed', w => { - this._settings.set_double('icon-saturation', w.get_value()); - }); - this.saturation_hbox.append(label); - this.saturation_hbox.append(widget); - - // Icon brightness - this.brightness_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Brightness (min: -1.0, max: 1.0)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1}); - widget.set_sensitive(true); - widget.set_range(-1.0, 1.0); - widget.set_value(this._settings.get_double('icon-brightness')); - widget.set_increments(0.1, 0.2); - widget.connect('value-changed', w => { - this._settings.set_double('icon-brightness', w.get_value()); - }); - this.brightness_hbox.append(label); - this.brightness_hbox.append(widget); - - // Icon contrast - this.contrast_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Contrast (min: -1.0, max: 1.0)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END, digits: 1}); - widget.set_sensitive(true); - widget.set_range(-1.0, 1.0); - widget.set_value(this._settings.get_double('icon-contrast')); - widget.set_increments(0.1, 0.2); - widget.connect('value-changed', w => { - this._settings.set_double('icon-contrast', w.get_value()); - }); - this.contrast_hbox.append(label); - this.contrast_hbox.append(widget); - - // Icon size - this.icon_size_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Icon size (min: 0, max: 96)'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.SpinButton({halign: Gtk.Align.END}); - widget.set_sensitive(true); - widget.set_range(0, 96); - widget.set_value(this._settings.get_int('icon-size')); - widget.set_increments(1, 2); - widget.connect('value-changed', w => { - this._settings.set_int('icon-size', w.get_value_as_int()); - }); - this.icon_size_hbox.append(label); - this.icon_size_hbox.append(widget); - - // Tray position in panel - this.tray_position_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 10, - margin_start: 10, - margin_end: 10, - margin_top: 10, - margin_bottom: 10, - }); - label = new Gtk.Label({ - label: _('Tray horizontal alignment'), - hexpand: true, - halign: Gtk.Align.START, - }); - widget = new Gtk.ComboBoxText(); - widget.append('center', _('Center')); - widget.append('left', _('Left')); - widget.append('right', _('Right')); - this._settings.bind('tray-pos', widget, 'active-id', - Gio.SettingsBindFlags.DEFAULT); - this.tray_position_hbox.append(label); - this.tray_position_hbox.append(widget); - - this.preferences_vbox.append(this.legacy_tray_hbox); - this.preferences_vbox.append(this.opacity_hbox); - this.preferences_vbox.append(this.saturation_hbox); - this.preferences_vbox.append(this.brightness_hbox); - this.preferences_vbox.append(this.contrast_hbox); - this.preferences_vbox.append(this.icon_size_hbox); - this.preferences_vbox.append(this.tray_position_hbox); - - // Custom icons section - - const customListStore = new Gtk.ListStore(); - customListStore.set_column_types([ - GObject.TYPE_STRING, - GObject.TYPE_STRING, - GObject.TYPE_STRING, - ]); - const customInitArray = this._settings.get_value('custom-icons').deep_unpack(); - customInitArray.forEach(pair => { - customListStore.set(customListStore.append(), [0, 1, 2], pair); - }); - customListStore.append(); - - const customTreeView = new Gtk.TreeView({ - model: customListStore, - hexpand: true, - vexpand: true, - }); - const customTitles = [ - _('Indicator ID'), - _('Icon Name'), - _('Attention Icon Name'), - ]; - const indicatorIdColumn = new Gtk.TreeViewColumn({ - title: customTitles[0], - sizing: Gtk.TreeViewColumnSizing.AUTOSIZE, - }); - const customIconColumn = new Gtk.TreeViewColumn({ - title: customTitles[1], - sizing: Gtk.TreeViewColumnSizing.AUTOSIZE, - }); - const customAttentionIconColumn = new Gtk.TreeViewColumn({ - title: customTitles[2], - sizing: Gtk.TreeViewColumnSizing.AUTOSIZE, - }); - - const cellrenderer = new Gtk.CellRendererText({editable: true}); - - indicatorIdColumn.pack_start(cellrenderer, true); - customIconColumn.pack_start(cellrenderer, true); - customAttentionIconColumn.pack_start(cellrenderer, true); - indicatorIdColumn.add_attribute(cellrenderer, 'text', 0); - customIconColumn.add_attribute(cellrenderer, 'text', 1); - customAttentionIconColumn.add_attribute(cellrenderer, 'text', 2); - customTreeView.insert_column(indicatorIdColumn, 0); - customTreeView.insert_column(customIconColumn, 1); - customTreeView.insert_column(customAttentionIconColumn, 2); - customTreeView.set_grid_lines(Gtk.TreeViewGridLines.BOTH); - - this.custom_icons_vbox.append(customTreeView); - - cellrenderer.connect('edited', (w, path, text) => { - this.selection = customTreeView.get_selection(); - const title = customTreeView.get_cursor()[1].get_title(); - const columnIndex = customTitles.indexOf(title); - const selection = this.selection.get_selected(); - const iter = selection.at(2); - const text2 = customListStore.get_value(iter, columnIndex ? 0 : 1); - customListStore.set(iter, [columnIndex], [text]); - const storeLength = customListStore.iter_n_children(null); - const customIconArray = []; - - for (let i = 0; i < storeLength; i++) { - const returnIter = customListStore.iter_nth_child(null, i); - const [success, iterList] = returnIter; - if (!success) - break; - - if (iterList) { - const id = customListStore.get_value(iterList, 0); - const customIcon = customListStore.get_value(iterList, 1); - const customAttentionIcon = customListStore.get_value(iterList, 2); - if (id && customIcon) - customIconArray.push([id, customIcon, customAttentionIcon || '']); - } else { - break; - } - } - this._settings.set_value('custom-icons', new GLib.Variant( - 'a(sss)', customIconArray)); - if (storeLength === 1 && (text || text2)) - customListStore.append(); - - if (storeLength > 1) { - if ((!text && !text2) && (storeLength - 1 > path)) - customListStore.remove(iter); - if ((text || text2) && storeLength - 1 <= path) - customListStore.append(); - } - }); - - this.notebook = new Gtk.Notebook(); - this.notebook.append_page(this.preferences_vbox, - new Gtk.Label({label: _('Preferences')})); - this.notebook.append_page(this.custom_icons_vbox, - new Gtk.Label({label: _('Custom Icons')})); - - this.append(this.notebook); - } -}); - -export default class DockPreferences extends ExtensionPreferences { - getPreferencesWidget() { - return new AppIndicatorPreferences(this); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js deleted file mode 100755 index 2749b037..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/promiseUtils.js +++ /dev/null @@ -1,324 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Meta from 'gi://GdkPixbuf'; - -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -export class CancellablePromise extends Promise { - constructor(executor, cancellable) { - if (!(executor instanceof Function)) - throw TypeError('executor is not a function'); - - if (cancellable && !(cancellable instanceof Gio.Cancellable)) - throw TypeError('cancellable parameter is not a Gio.Cancellable'); - - let rejector; - let resolver; - super((resolve, reject) => { - resolver = resolve; - rejector = reject; - }); - - const {stack: promiseStack} = new Error(); - this._promiseStack = promiseStack; - - this._resolver = (...args) => { - resolver(...args); - this._resolved = true; - this._cleanup(); - }; - this._rejector = (...args) => { - rejector(...args); - this._rejected = true; - this._cleanup(); - }; - - if (!cancellable) { - executor(this._resolver, this._rejector); - return; - } - - this._cancellable = cancellable; - this._cancelled = cancellable.is_cancelled(); - if (this._cancelled) { - this._rejector(new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.CANCELLED, 'Promise cancelled')); - return; - } - - this._cancellationId = cancellable.connect(() => { - const id = this._cancellationId; - this._cancellationId = 0; - GLib.idle_add(GLib.PRIORITY_DEFAULT, () => cancellable.disconnect(id)); - this.cancel(); - }); - - executor(this._resolver, this._rejector); - } - - _cleanup() { - if (this._cancellationId) - this._cancellable.disconnect(this._cancellationId); - } - - get cancellable() { - return this._chainRoot._cancellable || null; - } - - get _chainRoot() { - return this._root ? this._root : this; - } - - then(...args) { - const ret = super.then(...args); - - /* Every time we call then() on this promise we'd get a new - * CancellablePromise however that won't have the properties that the - * root one has set, and then it won't be possible to cancel a promise - * chain from the last one. - * To allow this we keep track of the root promise, make sure that - * the same method on the root object is called during cancellation - * or any destruction method if you want this to work. */ - if (ret instanceof CancellablePromise) - ret._root = this._chainRoot; - - return ret; - } - - resolved() { - return !!this._chainRoot._resolved; - } - - rejected() { - return !!this._chainRoot._rejected; - } - - cancelled() { - return !!this._chainRoot._cancelled; - } - - pending() { - return !this.resolved() && !this.rejected(); - } - - cancel() { - if (this._root) { - this._root.cancel(); - return this; - } - - if (!this.pending()) - return this; - - this._cancelled = true; - const error = new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.CANCELLED, 'Promise cancelled'); - error.stack += `## Promise created at:\n${this._promiseStack}`; - this._rejector(error); - - return this; - } -} - -export class SignalConnectionPromise extends CancellablePromise { - constructor(object, signal, cancellable) { - if (arguments.length === 1 && object instanceof Function) { - super(object); - return; - } - - if (!(object.connect instanceof Function)) - throw new TypeError('Not a valid object'); - - if (object instanceof GObject.Object && - !GObject.signal_lookup(signal.split(':')[0], object.constructor.$gtype)) - throw new TypeError(`Signal ${signal} not found on object ${object}`); - - let id; - let destroyId; - super(resolve => { - let connectSignal; - if (object instanceof GObject.Object) - connectSignal = (sig, cb) => GObject.signal_connect(object, sig, cb); - else - connectSignal = (sig, cb) => object.connect(sig, cb); - - id = connectSignal(signal, (_obj, ...args) => { - if (!args.length) - resolve(); - else - resolve(args.length === 1 ? args[0] : args); - }); - - if (signal !== 'destroy' && - (!(object instanceof GObject.Object) || - GObject.signal_lookup('destroy', object.constructor.$gtype))) - destroyId = connectSignal('destroy', () => this.cancel()); - }, cancellable); - - this._object = object; - this._id = id; - this._destroyId = destroyId; - } - - _cleanup() { - if (this._id) { - let disconnectSignal; - - if (this._object instanceof GObject.Object) - disconnectSignal = id => GObject.signal_handler_disconnect(this._object, id); - else - disconnectSignal = id => this._object.disconnect(id); - - disconnectSignal(this._id); - if (this._destroyId) { - disconnectSignal(this._destroyId); - this._destroyId = 0; - } - this._object = null; - this._id = 0; - } - - super._cleanup(); - } - - get object() { - return this._chainRoot._object; - } -} - -export class GSourcePromise extends CancellablePromise { - constructor(gsource, priority, cancellable) { - if (arguments.length === 1 && gsource instanceof Function) { - super(gsource); - return; - } - - if (gsource.constructor.$gtype !== GLib.Source.$gtype) - throw new TypeError(`gsource ${gsource} is not of type GLib.Source`); - - if (priority === undefined) - priority = GLib.PRIORITY_DEFAULT; - else if (!Number.isInteger(priority)) - throw TypeError('Invalid priority'); - - super(resolve => { - gsource.set_priority(priority); - gsource.set_callback(() => { - resolve(); - return GLib.SOURCE_REMOVE; - }); - gsource.attach(null); - }, cancellable); - - this._gsource = gsource; - this._gsource.set_name(`[gnome-shell] ${this.constructor.name} ${ - new Error().stack.split('\n').filter(line => - !line.match(/misc\/promiseUtils\.js/))[0]}`); - - if (this.rejected()) - this._gsource.destroy(); - } - - get gsource() { - return this._chainRoot._gsource; - } - - _cleanup() { - if (this._gsource) { - this._gsource.destroy(); - this._gsource = null; - } - super._cleanup(); - } -} - -export class IdlePromise extends GSourcePromise { - constructor(priority, cancellable) { - if (arguments.length === 1 && priority instanceof Function) { - super(priority); - return; - } - - if (priority === undefined) - priority = GLib.PRIORITY_DEFAULT_IDLE; - - super(GLib.idle_source_new(), priority, cancellable); - } -} - -export class TimeoutPromise extends GSourcePromise { - constructor(interval, priority, cancellable) { - if (arguments.length === 1 && interval instanceof Function) { - super(interval); - return; - } - - if (!Number.isInteger(interval) || interval < 0) - throw TypeError('Invalid interval'); - - super(GLib.timeout_source_new(interval), priority, cancellable); - } -} - -export class TimeoutSecondsPromise extends GSourcePromise { - constructor(interval, priority, cancellable) { - if (arguments.length === 1 && interval instanceof Function) { - super(interval); - return; - } - - if (!Number.isInteger(interval) || interval < 0) - throw TypeError('Invalid interval'); - - super(GLib.timeout_source_new_seconds(interval), priority, cancellable); - } -} - -export class MetaLaterPromise extends CancellablePromise { - constructor(laterType, cancellable) { - if (arguments.length === 1 && laterType instanceof Function) { - super(laterType); - return; - } - - if (laterType && laterType.constructor.$gtype !== Meta.LaterType.$gtype) - throw new TypeError(`laterType ${laterType} is not of type Meta.LaterType`); - else if (!laterType) - laterType = Meta.LaterType.BEFORE_REDRAW; - - let id; - super(resolve => { - id = Meta.later_add(laterType, () => { - this.remove(); - resolve(); - return GLib.SOURCE_REMOVE; - }); - }, cancellable); - - this._id = id; - } - - _cleanup() { - if (this._id) { - Meta.later_remove(this._id); - this._id = 0; - } - super._cleanup(); - } -} - -export function _promisifySignals(proto) { - if (proto.connect_once) - return; - - proto.connect_once = function (signal, cancellable) { - return new SignalConnectionPromise(this, signal, cancellable); - }; -} - -_promisifySignals(GObject.Object.prototype); -_promisifySignals(Signals.EventEmitter.prototype); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/gschemas.compiled deleted file mode 100755 index 65205698..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml deleted file mode 100755 index 75bba7ce..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/schemas/org.gnome.shell.extensions.appindicator.gschema.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - true - Enable legacy tray icons support - - - 0.0 - Saturation - - - 0.0 - Brightness - - - 0.0 - Contrast - - - 240 - Opacity - - - 0 - Icon size - Icon size in pixel - - - 12 - Icon spacing - Icon spacing within the tray - - - "right" - Position in tray - Set where the Icon tray should appear in Gnome tray - - - 1 - Order in tray - Set where the Icon tray should appear among other trays - - - [] - Custom icons - Replace any icons with custom icons from themes - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js deleted file mode 100755 index 6d943b92..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/settingsManager.js +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -let settingsManager; - -export class SettingsManager { - static initialize(extension) { - SettingsManager._settingsManager = new SettingsManager(extension); - } - - static destroy() { - SettingsManager._settingsManager.destroy(); - SettingsManager._settingsManager = null; - } - - static getDefault() { - return this._settingsManager; - } - - get gsettings() { - return this._gsettings; - } - - constructor(extension) { - if (settingsManager) - throw new Error('SettingsManager is already constructed'); - - this._gsettings = extension.getSettings(); - } - - destroy() { - this._gsettings = null; - } -} - -export function getDefault() { - return SettingsManager.getDefault(); -} - -export function getDefaultGSettings() { - return SettingsManager.getDefault().gsettings; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js deleted file mode 100755 index 915c860e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js +++ /dev/null @@ -1,287 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - -import * as AppIndicator from './appIndicator.js'; -import * as IndicatorStatusIcon from './indicatorStatusIcon.js'; -import * as Interfaces from './interfaces.js'; -import * as PromiseUtils from './promiseUtils.js'; -import * as Util from './util.js'; -import * as DBusMenu from './dbusMenu.js'; - -import {DBusProxy} from './dbusProxy.js'; - - -// TODO: replace with org.freedesktop and /org/freedesktop when approved -const KDE_PREFIX = 'org.kde'; - -export const WATCHER_BUS_NAME = `${KDE_PREFIX}.StatusNotifierWatcher`; -const WATCHER_OBJECT = '/StatusNotifierWatcher'; - -const DEFAULT_ITEM_OBJECT_PATH = '/StatusNotifierItem'; - -/* - * The StatusNotifierWatcher class implements the StatusNotifierWatcher dbus object - */ -export class StatusNotifierWatcher { - constructor(watchDog) { - this._watchDog = watchDog; - this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(Interfaces.StatusNotifierWatcher, this); - try { - this._dbusImpl.export(Gio.DBus.session, WATCHER_OBJECT); - } catch (e) { - Util.Logger.warn(`Failed to export ${WATCHER_OBJECT}`); - logError(e); - } - this._cancellable = new Gio.Cancellable(); - this._everAcquiredName = false; - this._ownName = Gio.DBus.session.own_name(WATCHER_BUS_NAME, - Gio.BusNameOwnerFlags.NONE, - this._acquiredName.bind(this), - this._lostName.bind(this)); - this._items = new Map(); - - try { - this._dbusImpl.emit_signal('StatusNotifierHostRegistered', null); - } catch (e) { - Util.Logger.warn(`Failed to notify registered host ${WATCHER_OBJECT}`); - } - - this._seekStatusNotifierItems().catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'Looking for StatusNotifierItem\'s'); - }); - } - - _acquiredName() { - this._everAcquiredName = true; - this._watchDog.nameAcquired = true; - } - - _lostName() { - if (this._everAcquiredName) - Util.Logger.debug(`Lost name${WATCHER_BUS_NAME}`); - else - Util.Logger.warn(`Failed to acquire ${WATCHER_BUS_NAME}`); - this._watchDog.nameAcquired = false; - } - - async _registerItem(service, busName, objPath) { - const id = Util.indicatorId(service, busName, objPath); - - if (this._items.has(id)) { - Util.Logger.warn(`Item ${id} is already registered`); - return; - } - - Util.Logger.debug(`Registering StatusNotifierItem ${id}`); - - try { - const indicator = new AppIndicator.AppIndicator(service, busName, objPath); - this._items.set(id, indicator); - indicator.connect('destroy', () => this._onIndicatorDestroyed(indicator)); - - indicator.connect('name-owner-changed', async () => { - if (!indicator.hasNameOwner) { - try { - await new PromiseUtils.TimeoutPromise(500, - GLib.PRIORITY_DEFAULT, this._cancellable); - if (this._items.has(id) && !indicator.hasNameOwner) - indicator.destroy(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - }); - - // if the desktop is not ready delay the icon creation and signal emissions - await Util.waitForStartupCompletion(indicator.cancellable); - const statusIcon = new IndicatorStatusIcon.IndicatorStatusIcon(indicator); - IndicatorStatusIcon.addIconToPanel(statusIcon); - - this._dbusImpl.emit_signal('StatusNotifierItemRegistered', - GLib.Variant.new('(s)', [indicator.uniqueId])); - this._dbusImpl.emit_property_changed('RegisteredStatusNotifierItems', - GLib.Variant.new('as', this.RegisteredStatusNotifierItems)); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - throw e; - } - } - - async _ensureItemRegistered(service, busName, objPath) { - const id = Util.indicatorId(service, busName, objPath); - const item = this._items.get(id); - - if (item) { - // delete the old one and add the new indicator - Util.Logger.debug(`Attempting to re-register ${id}; resetting instead`); - item.reset(); - return; - } - - await this._registerItem(service, busName, objPath); - } - - async _seekStatusNotifierItems() { - // Some indicators (*coff*, dropbox, *coff*) do not re-register again - // when the plugin is enabled/disabled, thus we need to manually look - // for the objects in the session bus that implements the - // StatusNotifierItem interface... However let's do it after a low - // priority idle, so that it won't affect startup. - const cancellable = this._cancellable; - const bus = Gio.DBus.session; - const uniqueNames = await Util.getBusNames(bus, cancellable); - const introspectName = async name => { - const nodes = Util.introspectBusObject(bus, name, cancellable, - ['org.kde.StatusNotifierItem']); - const services = [...uniqueNames.get(name)]; - - for await (const node of nodes) { - const {path} = node; - const ids = services.map(s => Util.indicatorId(s, name, path)); - if (ids.every(id => !this._items.has(id))) { - const service = services.find(s => - s && s.startsWith('org.kde.StatusNotifierItem')) || services[0]; - const id = Util.indicatorId( - path === DEFAULT_ITEM_OBJECT_PATH ? service : null, - name, path); - Util.Logger.warn(`Using Brute-force mode for StatusNotifierItem ${id}`); - this._registerItem(service, name, path); - } - } - }; - await Promise.allSettled([...uniqueNames.keys()].map(n => introspectName(n))); - } - - async RegisterStatusNotifierItemAsync(params, invocation) { - // it would be too easy if all application behaved the same - // instead, ayatana patched gnome apps to send a path - // while kde apps send a bus name - const [service] = params; - let busName, objPath; - - if (service.charAt(0) === '/') { // looks like a path - busName = invocation.get_sender(); - objPath = service; - } else if (service.match(Util.BUS_ADDRESS_REGEX)) { - try { - busName = await Util.getUniqueBusName(invocation.get_connection(), - service, this._cancellable); - } catch (e) { - logError(e); - } - objPath = DEFAULT_ITEM_OBJECT_PATH; - } - - if (!busName || !objPath) { - const error = `Impossible to register an indicator for parameters '${ - service.toString()}'`; - Util.Logger.warn(error); - - invocation.return_dbus_error('org.gnome.gjs.JSError.ValueError', - error); - return; - } - - try { - await this._ensureItemRegistered(service, busName, objPath); - invocation.return_value(null); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - invocation.return_dbus_error('org.gnome.gjs.JSError.ValueError', - e.message); - } - } - - _onIndicatorDestroyed(indicator) { - const {uniqueId} = indicator; - this._items.delete(uniqueId); - - try { - this._dbusImpl.emit_signal('StatusNotifierItemUnregistered', - GLib.Variant.new('(s)', [uniqueId])); - this._dbusImpl.emit_property_changed('RegisteredStatusNotifierItems', - GLib.Variant.new('as', this.RegisteredStatusNotifierItems)); - } catch (e) { - Util.Logger.warn(`Failed to emit signals: ${e}`); - } - } - - RegisterStatusNotifierHostAsync(_service, invocation) { - invocation.return_error_literal( - Gio.DBusError, - Gio.DBusError.NOT_SUPPORTED, - 'Registering additional notification hosts is not supported'); - } - - IsNotificationHostRegistered() { - return true; - } - - get RegisteredStatusNotifierItems() { - return Array.from(this._items.values()).map(i => i.uniqueId); - } - - get IsStatusNotifierHostRegistered() { - return true; - } - - get ProtocolVersion() { - return 0; - } - - destroy() { - if (this._isDestroyed) - return; - - // this doesn't do any sync operation and doesn't allow us to hook up - // the event of being finished which results in our unholy debounce hack - // (see extension.js) - this._items.forEach(indicator => indicator.destroy()); - this._cancellable.cancel(); - - try { - this._dbusImpl.emit_signal('StatusNotifierHostUnregistered', null); - } catch (e) { - Util.Logger.warn(`Failed to emit uinregistered signal: ${e}`); - } - - Gio.DBus.session.unown_name(this._ownName); - - try { - this._dbusImpl.unexport(); - } catch (e) { - Util.Logger.warn(`Failed to unexport watcher object: ${e}`); - } - - DBusMenu.DBusClient.destroy(); - AppIndicator.AppIndicatorProxy.destroy(); - DBusProxy.destroy(); - Util.destroyDefaultTheme(); - - this._dbusImpl.run_dispose(); - delete this._dbusImpl; - - delete this._items; - this._isDestroyed = true; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js deleted file mode 100755 index cdc2a8ea..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/trayIconsManager.js +++ /dev/null @@ -1,104 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import Shell from 'gi://Shell'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import * as IndicatorStatusIcon from './indicatorStatusIcon.js'; -import * as Util from './util.js'; -import * as SettingsManager from './settingsManager.js'; - -let trayIconsManager; - -export class TrayIconsManager extends Signals.EventEmitter { - static initialize() { - if (!trayIconsManager) - trayIconsManager = new TrayIconsManager(); - return trayIconsManager; - } - - static destroy() { - trayIconsManager.destroy(); - } - - constructor() { - super(); - - if (trayIconsManager) - throw new Error('TrayIconsManager is already constructed'); - - this._changedId = SettingsManager.getDefaultGSettings().connect( - 'changed::legacy-tray-enabled', () => this._toggle()); - - this._toggle(); - } - - _toggle() { - if (SettingsManager.getDefaultGSettings().get_boolean('legacy-tray-enabled')) - this._enable(); - else - this._disable(); - } - - _enable() { - if (this._tray) - return; - - this._tray = new Shell.TrayManager(); - Util.connectSmart(this._tray, 'tray-icon-added', this, this.onTrayIconAdded); - Util.connectSmart(this._tray, 'tray-icon-removed', this, this.onTrayIconRemoved); - - this._tray.manage_screen(Main.panel); - } - - _disable() { - if (!this._tray) - return; - - IndicatorStatusIcon.getTrayIcons().forEach(i => i.destroy()); - if (this._tray.unmanage_screen) { - this._tray.unmanage_screen(); - this._tray = null; - } else { - // FIXME: This is very ugly, but it's needed by old shell versions - this._tray = null; - imports.system.gc(); // force finalizing tray to unmanage screen - } - } - - onTrayIconAdded(_tray, icon) { - const trayIcon = new IndicatorStatusIcon.IndicatorStatusTrayIcon(icon); - IndicatorStatusIcon.addIconToPanel(trayIcon); - } - - onTrayIconRemoved(_tray, icon) { - try { - const [trayIcon] = IndicatorStatusIcon.getTrayIcons().filter(i => i.icon === icon); - trayIcon.destroy(); - } catch (e) { - Util.Logger.warning(`No icon container found for ${icon.title} (${icon})`); - } - } - - destroy() { - this.emit('destroy'); - SettingsManager.getDefaultGSettings().disconnect(this._changedId); - this._disable(); - trayIconsManager = null; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js deleted file mode 100755 index 0aba2444..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js +++ /dev/null @@ -1,447 +0,0 @@ -// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Config from 'resource:///org/gnome/shell/misc/config.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import {BaseStatusIcon} from './indicatorStatusIcon.js'; - -export const BUS_ADDRESS_REGEX = /([a-zA-Z0-9._-]+\.[a-zA-Z0-9.-]+)|(:[0-9]+\.[0-9]+)$/; - -Gio._promisify(Gio.DBusConnection.prototype, 'call'); -Gio._promisify(Gio._LocalFilePrototype, 'read'); -Gio._promisify(Gio.InputStream.prototype, 'read_bytes_async'); - -export function indicatorId(service, busName, objectPath) { - if (service !== busName && service?.match(BUS_ADDRESS_REGEX)) - return service; - - return `${busName}@${objectPath}`; -} - -export async function getUniqueBusName(bus, name, cancellable) { - if (name[0] === ':') - return name; - - if (!bus) - bus = Gio.DBus.session; - - const variantName = new GLib.Variant('(s)', [name]); - const [unique] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', - 'GetNameOwner', variantName, new GLib.VariantType('(s)'), - Gio.DBusCallFlags.NONE, -1, cancellable)).deep_unpack(); - - return unique; -} - -export async function getBusNames(bus, cancellable) { - if (!bus) - bus = Gio.DBus.session; - - const [names] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', - 'ListNames', null, new GLib.VariantType('(as)'), Gio.DBusCallFlags.NONE, - -1, cancellable)).deep_unpack(); - - const uniqueNames = new Map(); - const requests = names.map(name => getUniqueBusName(bus, name, cancellable)); - const results = await Promise.allSettled(requests); - - for (let i = 0; i < results.length; i++) { - const result = results[i]; - if (result.status === 'fulfilled') { - let namesForBus = uniqueNames.get(result.value); - if (!namesForBus) { - namesForBus = new Set(); - uniqueNames.set(result.value, namesForBus); - } - namesForBus.add(result.value !== names[i] ? names[i] : null); - } else if (!result.reason.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Logger.debug(`Impossible to get the unique name of ${names[i]}: ${result.reason}`); - } - } - - return uniqueNames; -} - -async function getProcessId(connectionName, cancellable = null, bus = Gio.DBus.session) { - const res = await bus.call('org.freedesktop.DBus', '/', - 'org.freedesktop.DBus', 'GetConnectionUnixProcessID', - new GLib.Variant('(s)', [connectionName]), - new GLib.VariantType('(u)'), - Gio.DBusCallFlags.NONE, - -1, - cancellable); - const [pid] = res.deepUnpack(); - return pid; -} - -export async function getProcessName(connectionName, cancellable = null, - priority = GLib.PRIORITY_DEFAULT, bus = Gio.DBus.session) { - const pid = await getProcessId(connectionName, cancellable, bus); - const cmdFile = Gio.File.new_for_path(`/proc/${pid}/cmdline`); - const inputStream = await cmdFile.read_async(priority, cancellable); - const bytes = await inputStream.read_bytes_async(2048, priority, cancellable); - const textDecoder = new TextDecoder(); - return textDecoder.decode(bytes.toArray().map(v => !v ? 0x20 : v)); -} - -export async function* introspectBusObject(bus, name, cancellable, - interfaces = undefined, path = undefined) { - if (!path) - path = '/'; - - const [introspection] = (await bus.call(name, path, 'org.freedesktop.DBus.Introspectable', - 'Introspect', null, new GLib.VariantType('(s)'), Gio.DBusCallFlags.NONE, - 5000, cancellable)).deep_unpack(); - - const nodeInfo = Gio.DBusNodeInfo.new_for_xml(introspection); - - if (!interfaces || dbusNodeImplementsInterfaces(nodeInfo, interfaces)) - yield {nodeInfo, path}; - - if (path === '/') - path = ''; - - for (const subNodeInfo of nodeInfo.nodes) { - const subPath = `${path}/${subNodeInfo.path}`; - yield* introspectBusObject(bus, name, cancellable, interfaces, subPath); - } -} - -function dbusNodeImplementsInterfaces(nodeInfo, interfaces) { - if (!(nodeInfo instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces)) - return false; - - return interfaces.some(iface => nodeInfo.lookup_interface(iface)); -} - -export class NameWatcher extends Signals.EventEmitter { - constructor(name) { - super(); - - this._watcherId = Gio.DBus.session.watch_name(name, - Gio.BusNameWatcherFlags.NONE, () => { - this._nameOnBus = true; - Logger.debug(`Name ${name} appeared`); - this.emit('changed'); - this.emit('appeared'); - }, () => { - this._nameOnBus = false; - Logger.debug(`Name ${name} vanished`); - this.emit('changed'); - this.emit('vanished'); - }); - } - - destroy() { - this.emit('destroy'); - - Gio.DBus.session.unwatch_name(this._watcherId); - delete this._watcherId; - } - - get nameOnBus() { - return !!this._nameOnBus; - } -} - -function connectSmart3A(src, signal, handler) { - const id = src.connect(signal, handler); - let destroyId = 0; - - if (src.connect && (!(src instanceof GObject.Object) || GObject.signal_lookup('destroy', src))) { - destroyId = src.connect('destroy', () => { - src.disconnect(id); - src.disconnect(destroyId); - }); - } - - return [id, destroyId]; -} - -function connectSmart4A(src, signal, target, method) { - if (typeof method !== 'function') - throw new TypeError('Unsupported function'); - - method = method.bind(target); - const signalId = src.connect(signal, method); - const onDestroy = () => { - src.disconnect(signalId); - if (srcDestroyId) - src.disconnect(srcDestroyId); - if (tgtDestroyId) - target.disconnect(tgtDestroyId); - }; - - // GObject classes might or might not have a destroy signal - // JS Classes will not complain when connecting to non-existent signals - const srcDestroyId = src.connect && (!(src instanceof GObject.Object) || - GObject.signal_lookup('destroy', src)) ? src.connect('destroy', onDestroy) : 0; - const tgtDestroyId = target.connect && (!(target instanceof GObject.Object) || - GObject.signal_lookup('destroy', target)) ? target.connect('destroy', onDestroy) : 0; - - return [signalId, srcDestroyId, tgtDestroyId]; -} - -// eslint-disable-next-line valid-jsdoc -/** - * Connect signals to slots, and remove the connection when either source or - * target are destroyed - * - * Usage: - * Util.connectSmart(srcOb, 'signal', tgtObj, 'handler') - * or - * Util.connectSmart(srcOb, 'signal', () => { ... }) - */ -export function connectSmart(...args) { - if (arguments.length === 4) - return connectSmart4A(...args); - else - return connectSmart3A(...args); -} - -function disconnectSmart3A(src, signalIds) { - const [id, destroyId] = signalIds; - src.disconnect(id); - - if (destroyId) - src.disconnect(destroyId); -} - -function disconnectSmart4A(src, tgt, signalIds) { - const [signalId, srcDestroyId, tgtDestroyId] = signalIds; - - disconnectSmart3A(src, [signalId, srcDestroyId]); - - if (tgtDestroyId) - tgt.disconnect(tgtDestroyId); -} - -export function disconnectSmart(...args) { - if (arguments.length === 2) - return disconnectSmart3A(...args); - else if (arguments.length === 3) - return disconnectSmart4A(...args); - - throw new TypeError('Unexpected number of arguments'); -} - -let _defaultTheme; -export function getDefaultTheme() { - if (_defaultTheme) - return _defaultTheme; - - _defaultTheme = new St.IconTheme(); - return _defaultTheme; -} - -export function destroyDefaultTheme() { - _defaultTheme = null; -} - -// eslint-disable-next-line valid-jsdoc -/** - * Helper function to wait for the system startup to be completed. - * Adding widgets before the desktop is ready to accept them can result in errors. - */ -export async function waitForStartupCompletion(cancellable) { - if (Main.layoutManager._startingUp) - await Main.layoutManager.connect_once('startup-complete', cancellable); -} - -/** - * Helper class for logging stuff - */ -export class Logger { - static _logStructured(logLevel, message, extraFields = {}) { - if (!Object.values(GLib.LogLevelFlags).includes(logLevel)) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, - 'logLevel is not a valid GLib.LogLevelFlags'); - return; - } - - if (!Logger._levels.includes(logLevel)) - return; - - let fields = { - 'SYSLOG_IDENTIFIER': this.uuid, - 'MESSAGE': `${message}`, - }; - - let thisFile = null; - const {stack} = new Error(); - for (let stackLine of stack.split('\n')) { - stackLine = stackLine.replace('resource:///org/gnome/Shell/', ''); - const [code, line] = stackLine.split(':'); - const [func, file] = code.split(/@(.+)/); - - if (!thisFile || thisFile === file) { - thisFile = file; - continue; - } - - fields = Object.assign(fields, { - 'CODE_FILE': file || '', - 'CODE_LINE': line || '', - 'CODE_FUNC': func || '', - }); - - break; - } - - GLib.log_structured(Logger._domain, logLevel, Object.assign(fields, extraFields)); - } - - static init(extension) { - if (Logger._domain) - return; - - const allLevels = Object.values(GLib.LogLevelFlags); - const domains = GLib.getenv('G_MESSAGES_DEBUG'); - const {name: domain} = extension.metadata; - this.uuid = extension.metadata.uuid; - Logger._domain = domain.replaceAll(' ', '-'); - - if (domains === 'all' || (domains && domains.split(' ').includes(Logger._domain))) { - Logger._levels = allLevels; - } else { - Logger._levels = allLevels.filter( - l => l <= GLib.LogLevelFlags.LEVEL_WARNING); - } - } - - static debug(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_DEBUG, message); - } - - static message(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_MESSAGE, message); - } - - static warn(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, message); - } - - static error(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_ERROR, message); - } - - static critical(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_CRITICAL, message); - } -} - -export function versionCheck(required) { - const current = Config.PACKAGE_VERSION; - const currentArray = current.split('.'); - const [major] = currentArray; - return major >= required; -} - -export function tryCleanupOldIndicators() { - const indicatorType = BaseStatusIcon; - const indicators = Object.values(Main.panel.statusArea).filter(i => i instanceof indicatorType); - - try { - const panelBoxes = [ - Main.panel._leftBox, Main.panel._centerBox, Main.panel._rightBox, - ]; - - panelBoxes.forEach(box => - indicators.push(...box.get_children().filter(i => i instanceof indicatorType))); - } catch (e) { - logError(e); - } - - new Set(indicators).forEach(i => i.destroy()); -} - -export function addActor(obj, actor) { - if (obj.add_actor) - obj.add_actor(actor); - else - obj.add_child(actor); -} - -export function removeActor(obj, actor) { - if (obj.remove_actor) - obj.remove_actor(actor); - else - obj.remove_child(actor); -} - -export const CancellableChild = GObject.registerClass({ - Properties: { - 'parent': GObject.ParamSpec.object( - 'parent', 'parent', 'parent', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - Gio.Cancellable.$gtype), - }, -}, -class CancellableChild extends Gio.Cancellable { - _init(parent) { - if (parent && !(parent instanceof Gio.Cancellable)) - throw TypeError('Not a valid cancellable'); - - super._init({parent}); - - if (parent) { - if (parent.is_cancelled()) { - this.cancel(); - return; - } - - this._connectToParent(); - } - } - - _connectToParent() { - this._connectId = this.parent.connect(() => { - this._realCancel(); - - if (this._disconnectIdle) - return; - - this._disconnectIdle = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - delete this._disconnectIdle; - this._disconnectFromParent(); - return GLib.SOURCE_REMOVE; - }); - }); - } - - _disconnectFromParent() { - if (this._connectId && !this._disconnectIdle) { - this.parent.disconnect(this._connectId); - delete this._connectId; - } - } - - _realCancel() { - Gio.Cancellable.prototype.cancel.call(this); - } - - cancel() { - this._disconnectFromParent(); - this._realCancel(); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appmenu-is-back@fthx/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/appmenu-is-back@fthx/extension.js deleted file mode 100755 index ef4bc600..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appmenu-is-back@fthx/extension.js +++ /dev/null @@ -1,232 +0,0 @@ -// App Menu Is Back -// GNOME Shell extension -// @fthx 2024 -// Almost all the code comes from GS 44 original code - - -import Atk from 'gi://Atk'; -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as Animation from 'resource:///org/gnome/shell/ui/animation.js'; -import * as AppMenu from 'resource:///org/gnome/shell/ui/appMenu.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Overview from 'resource:///org/gnome/shell/ui/overview.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; - -const PANEL_ICON_SIZE = 16; -const APP_MENU_ICON_MARGIN = 0; - - -const AppMenuButton = GObject.registerClass({ - Signals: { 'changed': {} }, -}, class AppMenuButton extends PanelMenu.Button { - _init() { - super._init(0.0, null, true); - - this.accessible_role = Atk.Role.MENU; - - this._startingApps = []; - - this._menuManager = Main.panel.menuManager; - this._targetApp = null; - - let bin = new St.Bin({ name: 'appMenu' }); - this.add_child(bin); - - this.bind_property("reactive", this, "can-focus", 0); - this.reactive = false; - - this._container = new St.BoxLayout({ - style_class: 'panel-status-menu-box', - }); - bin.set_child(this._container); - - let textureCache = St.TextureCache.get_default(); - textureCache.connect('icon-theme-changed', - this._onIconThemeChanged.bind(this)); - - let iconEffect = new Clutter.DesaturateEffect(); - this._iconBox = new St.Bin({ - style_class: 'app-menu-icon', - y_align: Clutter.ActorAlign.CENTER, - }); - this._iconBox.add_effect(iconEffect); - this._container.add_child(this._iconBox); - - this._iconBox.connect('style-changed', () => { - let themeNode = this._iconBox.get_theme_node(); - iconEffect.enabled = themeNode.get_icon_style() == St.IconStyle.SYMBOLIC; - }); - - this._label = new St.Label({ - y_expand: true, - y_align: Clutter.ActorAlign.CENTER, - }); - this._container.add_child(this._label); - - this._visible = !Main.overview.visible; - if (!this._visible) - this.hide(); - Main.overview.connectObject( - 'hiding', this._sync.bind(this), - 'showing', this._sync.bind(this), this); - - this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, { - animate: true, - hideOnStop: true, - }); - this._container.add_child(this._spinner); - - let menu = new AppMenu.AppMenu(this); - this.setMenu(menu); - this._menuManager.addMenu(menu); - - Shell.WindowTracker.get_default().connectObject('notify::focus-app', - this._focusAppChanged.bind(this), this); - Shell.AppSystem.get_default().connectObject('app-state-changed', - this._onAppStateChanged.bind(this), this); - global.window_manager.connectObject('switch-workspace', - this._sync.bind(this), this); - - this._sync(); - } - - fadeIn() { - if (this._visible) - return; - - this._visible = true; - this.reactive = true; - this.remove_all_transitions(); - this.ease({ - opacity: 255, - duration: Overview.ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - - fadeOut() { - if (!this._visible) - return; - - this._visible = false; - this.reactive = false; - this.remove_all_transitions(); - this.ease({ - opacity: 0, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: Overview.ANIMATION_TIME, - }); - } - - _syncIcon(app) { - const icon = app.create_icon_texture(PANEL_ICON_SIZE - APP_MENU_ICON_MARGIN); - this._iconBox.set_child(icon); - } - - _onIconThemeChanged() { - if (this._iconBox.child == null) - return; - - if (this._targetApp) - this._syncIcon(this._targetApp); - } - - stopAnimation() { - this._spinner.stop(); - } - - startAnimation() { - this._spinner.play(); - } - - _onAppStateChanged(appSys, app) { - let state = app.state; - if (state != Shell.AppState.STARTING) - this._startingApps = this._startingApps.filter(a => a != app); - else if (state == Shell.AppState.STARTING) - this._startingApps.push(app); - this._sync(); - } - - _focusAppChanged() { - let tracker = Shell.WindowTracker.get_default(); - let focusedApp = tracker.focus_app; - if (!focusedApp) { - if (global.stage.key_focus != null) - return; - } - this._sync(); - } - - _findTargetApp() { - let workspaceManager = global.workspace_manager; - let workspace = workspaceManager.get_active_workspace(); - let tracker = Shell.WindowTracker.get_default(); - let focusedApp = tracker.focus_app; - if (focusedApp && focusedApp.is_on_workspace(workspace)) - return focusedApp; - - for (let i = 0; i < this._startingApps.length; i++) { - if (this._startingApps[i].is_on_workspace(workspace)) - return this._startingApps[i]; - } - - return null; - } - - _sync() { - let targetApp = this._findTargetApp(); - - if (this._targetApp != targetApp) { - this._targetApp?.disconnectObject(this); - - this._targetApp = targetApp; - - if (this._targetApp) { - this._targetApp.connectObject('notify::busy', this._sync.bind(this), this); - this._label.set_text(this._targetApp.get_name()); - this.set_accessible_name(this._targetApp.get_name()); - - this._syncIcon(this._targetApp); - } - } - - let visible = this._targetApp != null && !Main.overview.visibleTarget; - if (visible) - this.fadeIn(); - else - this.fadeOut(); - - let isBusy = this._targetApp != null && - (this._targetApp.get_state() == Shell.AppState.STARTING || - this._targetApp.get_busy()); - if (isBusy) - this.startAnimation(); - else - this.stopAnimation(); - - this.reactive = visible && !isBusy; - - this.menu.setApp(this._targetApp); - this.emit('changed'); - } -}); - -export default class AppMenuIsBackExtension { - enable() { - this._app_menu = new AppMenuButton(); - Main.panel.addToStatusArea('appmenu-indicator', this._app_menu, -1, 'left'); - } - - disable() { - Main.panel.menuManager.removeMenu(this._app_menu.menu); - this._app_menu.menu = null; - - this._app_menu.destroy(); - delete this._app_menu; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/appmenu-is-back@fthx/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/appmenu-is-back@fthx/metadata.json deleted file mode 100755 index 91b0f1f9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/appmenu-is-back@fthx/metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "The good old original app menu. For GNOME Shell 45+.\n\n Code mostly copied from GNOME Shell code itself. For a customizable app menu, please consider 'Window title is back' extension.", - "name": "App menu is back", - "shell-version": [ - "46" - ], - "url": "https://github.com/fthx/appmenu-is-back", - "uuid": "appmenu-is-back@fthx", - "version": 3 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/appfolders.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/appfolders.js deleted file mode 100755 index 309234d7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/appfolders.js +++ /dev/null @@ -1,255 +0,0 @@ -import Shell from 'gi://Shell'; -import Clutter from 'gi://Clutter'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../conveniences/paint_signals.js'; -// TODO drop Tweener in favour of Clutter's `ease` (will need to extend the blur effect for it) -const Tweener = imports.tweener.tweener; - -const transparent = Clutter.Color.from_pixel(0x00000000); -const FOLDER_DIALOG_ANIMATION_TIME = 200; - -const DIALOGS_STYLES = [ - "appfolder-dialogs-transparent", - "appfolder-dialogs-light", - "appfolder-dialogs-dark" -]; - -let original_zoomAndFadeIn = null; -let original_zoomAndFadeOut = null; -let sigma; -let brightness; - -let _zoomAndFadeIn = function () { - let [sourceX, sourceY] = - this._source.get_transformed_position(); - let [dialogX, dialogY] = - this.child.get_transformed_position(); - - this.child.set({ - translation_x: sourceX - dialogX, - translation_y: sourceY - dialogY, - scale_x: this._source.width / this.child.width, - scale_y: this._source.height / this.child.height, - opacity: 0, - }); - - this.set_background_color(transparent); - - let blur_effect = this.get_effect("appfolder-blur"); - - blur_effect.radius = 0; - blur_effect.brightness = 1.0; - Tweener.addTween(blur_effect, - { - radius: sigma * 2, - brightness: brightness, - time: FOLDER_DIALOG_ANIMATION_TIME / 1000, - transition: 'easeOutQuad' - } - ); - - this.child.ease({ - translation_x: 0, - translation_y: 0, - scale_x: 1, - scale_y: 1, - opacity: 255, - duration: FOLDER_DIALOG_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - - this._needsZoomAndFade = false; - - if (this._sourceMappedId === 0) { - this._sourceMappedId = this._source.connect( - 'notify::mapped', this._zoomAndFadeOut.bind(this)); - } -}; - -let _zoomAndFadeOut = function () { - if (!this._isOpen) - return; - - if (!this._source.mapped) { - this.hide(); - return; - } - - let [sourceX, sourceY] = - this._source.get_transformed_position(); - let [dialogX, dialogY] = - this.child.get_transformed_position(); - - this.set_background_color(transparent); - - let blur_effect = this.get_effect("appfolder-blur"); - Tweener.addTween(blur_effect, - { - radius: 0, - brightness: 1.0, - time: FOLDER_DIALOG_ANIMATION_TIME / 1000, - transition: 'easeInQuad' - } - ); - - this.child.ease({ - translation_x: sourceX - dialogX, - translation_y: sourceY - dialogY, - scale_x: this._source.width / this.child.width, - scale_y: this._source.height / this.child.height, - opacity: 0, - duration: FOLDER_DIALOG_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - this.child.set({ - translation_x: 0, - translation_y: 0, - scale_x: 1, - scale_y: 1, - opacity: 255, - }); - this.hide(); - - this._popdownCallbacks.forEach(func => func()); - this._popdownCallbacks = []; - }, - }); - - this._needsZoomAndFade = false; -}; - - -export const AppFoldersBlur = class AppFoldersBlur { - // we do not use the effects manager and dummy pipelines here because we - // really want to manage our sigma value ourself during the transition - constructor(connections, settings, _) { - this.connections = connections; - this.paint_signals = new PaintSignals(connections); - this.settings = settings; - } - - enable() { - this._log("blurring appfolders"); - - brightness = this.settings.appfolder.BRIGHTNESS; - sigma = this.settings.appfolder.SIGMA; - - let appDisplay = Main.overview._overview.controls._appDisplay; - - if (appDisplay._folderIcons.length > 0) { - this.blur_appfolders(); - } - - this.connections.connect( - appDisplay, 'view-loaded', _ => this.blur_appfolders() - ); - } - - blur_appfolders() { - let appDisplay = Main.overview._overview.controls._appDisplay; - - if (this.settings.HACKS_LEVEL === 1) - this._log("appfolders hack level 1"); - - appDisplay._folderIcons.forEach(icon => { - icon._ensureFolderDialog(); - - if (original_zoomAndFadeIn == null) { - original_zoomAndFadeIn = icon._dialog._zoomAndFadeIn; - } - if (original_zoomAndFadeOut == null) { - original_zoomAndFadeOut = icon._dialog._zoomAndFadeOut; - } - - let blur_effect = new Shell.BlurEffect({ - name: "appfolder-blur", - radius: sigma * 2, - brightness: brightness, - mode: Shell.BlurMode.BACKGROUND - }); - - icon._dialog.remove_effect_by_name("appfolder-blur"); - icon._dialog.add_effect(blur_effect); - - DIALOGS_STYLES.forEach( - style => icon._dialog._viewBox.remove_style_class_name(style) - ); - - if (this.settings.appfolder.STYLE_DIALOGS > 0) - icon._dialog._viewBox.add_style_class_name( - DIALOGS_STYLES[this.settings.appfolder.STYLE_DIALOGS - 1] - ); - - // finally override the builtin functions - icon._dialog._zoomAndFadeIn = _zoomAndFadeIn; - icon._dialog._zoomAndFadeOut = _zoomAndFadeOut; - - - // HACK - // - //`Shell.BlurEffect` does not repaint when shadows are under it. [1] - // - // This does not entirely fix this bug (shadows caused by windows - // still cause artifacts), but it prevents the shadows of the panel - // buttons to cause artifacts on the panel itself - // - // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857 - - if (this.settings.HACKS_LEVEL === 1) { - this.paint_signals.disconnect_all_for_actor(icon._dialog); - this.paint_signals.connect(icon._dialog, blur_effect); - } else { - this.paint_signals.disconnect_all(); - } - }); - }; - - set_sigma(s) { - sigma = s; - if (this.settings.appfolder.BLUR) - this.blur_appfolders(); - } - - set_brightness(b) { - brightness = b; - if (this.settings.appfolder.BLUR) - this.blur_appfolders(); - } - - disable() { - this._log("removing blur from appfolders"); - - let appDisplay = Main.overview._overview.controls._appDisplay; - - if (original_zoomAndFadeIn != null) { - appDisplay._folderIcons.forEach(icon => { - if (icon._dialog) - icon._dialog._zoomAndFadeIn = original_zoomAndFadeIn; - }); - } - - if (original_zoomAndFadeOut != null) { - appDisplay._folderIcons.forEach(icon => { - if (icon._dialog) - icon._dialog._zoomAndFadeOut = original_zoomAndFadeOut; - }); - } - - appDisplay._folderIcons.forEach(icon => { - if (icon._dialog) { - icon._dialog.remove_effect_by_name("appfolder-blur"); - DIALOGS_STYLES.forEach( - s => icon._dialog._viewBox.remove_style_class_name(s) - ); - } - }); - - this.connections.disconnect_all(); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > appfolders] ${str}`); - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/applications.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/applications.js deleted file mode 100755 index e2a8bdf9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/applications.js +++ /dev/null @@ -1,451 +0,0 @@ -import Meta from 'gi://Meta'; -import Gio from 'gi://Gio'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { ApplicationsService } from '../dbus/services.js'; -import { PaintSignals } from '../conveniences/paint_signals.js'; -import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; - -export const ApplicationsBlur = class ApplicationsBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.settings = settings; - this.effects_manager = effects_manager; - this.paint_signals = new PaintSignals(connections); - - // stores every blurred meta window - this.meta_window_map = new Map(); - } - - enable() { - this._log("blurring applications..."); - - // export dbus service for preferences - this.service = new ApplicationsService; - this.service.export(); - - this.mutter_gsettings = new Gio.Settings({ schema: 'org.gnome.mutter' }); - - // blur already existing windows - this.update_all_windows(); - - // blur every new window - this.connections.connect( - global.display, - 'window-created', - (_meta_display, meta_window) => { - this._log("window created"); - - if (meta_window) - this.track_new(meta_window); - } - ); - - // update window blur when focus is changed - this.focused_window_pid = null; - this.init_dynamic_opacity(); - this.connections.connect( - global.display, - 'focus-window', - (_meta_display, meta_window, _p0) => { - if (meta_window && meta_window.bms_pid != this.focused_window_pid) - this.set_focus_for_window(meta_window); - else if (!meta_window) - this.set_focus_for_window(null); - } - ); - - this.connect_to_overview(); - } - - /// Initializes the dynamic opacity for windows, without touching to the connections. - /// This is used both when enabling the component, and when changing the dynamic-opacity pref. - init_dynamic_opacity() { - if (this.settings.applications.DYNAMIC_OPACITY) { - // make the currently focused window solid - if (global.display.focus_window) - this.set_focus_for_window(global.display.focus_window); - } else { - // remove old focused window if the pref was changed - if (this.focused_window_pid) - this.set_focus_for_window(null); - } - } - - /// Connect to the overview being opened/closed to force the blur being - /// shown on every window of the workspaces viewer. - connect_to_overview() { - this.connections.disconnect_all_for(Main.overview); - - if (this.settings.applications.BLUR_ON_OVERVIEW) { - // when the overview is opened, show every window actors (which - // allows the blur to be shown too) - this.connections.connect( - Main.overview, 'showing', - _ => this.meta_window_map.forEach((meta_window, _pid) => { - let window_actor = meta_window.get_compositor_private(); - window_actor?.show(); - }) - ); - - // when the overview is closed, hide every actor that is not on the - // current workspace (to mimic the original behaviour) - this.connections.connect( - Main.overview, 'hidden', - _ => { - this.meta_window_map.forEach((meta_window, _pid) => { - let window_actor = meta_window.get_compositor_private(); - - if ( - !meta_window.get_workspace().active - ) - window_actor.hide(); - }); - } - ); - } - } - - /// Iterate through all existing windows and add blur as needed. - update_all_windows() { - // remove all previously blurred windows, in the case where the - // whitelist was changed - this.meta_window_map.forEach(((_meta_window, pid) => { - this.remove_blur(pid); - })); - - for ( - let i = 0; - i < global.workspace_manager.get_n_workspaces(); - ++i - ) { - let workspace = global.workspace_manager.get_workspace_by_index(i); - let windows = workspace.list_windows(); - - windows.forEach(meta_window => this.track_new(meta_window)); - } - } - - /// Adds the needed signals to every new tracked window, and adds blur if - /// needed. - /// Accepts only untracked meta windows (i.e no `bms_pid` set) - track_new(meta_window) { - // create a pid that will follow the window during its whole life - const pid = ("" + Math.random()).slice(2, 16); - meta_window.bms_pid = pid; - - this._log(`new window tracked, pid: ${pid}`); - - // register the blurred window - this.meta_window_map.set(pid, meta_window); - - // update the blur when wm-class is changed - this.connections.connect( - meta_window, 'notify::wm-class', - _ => this.check_blur(meta_window) - ); - - // update the position and size when the window size changes - this.connections.connect( - meta_window, 'size-changed', - _ => this.update_size(pid) - ); - - // remove the blur when the window is unmanaged - this.connections.connect( - meta_window, 'unmanaging', - _ => this.untrack_meta_window(pid) - ); - - this.check_blur(meta_window); - } - - /// Updates the size of the blur actor associated to a meta window from its pid. - /// Accepts only tracked meta window (i.e `bms_pid` set), be it blurred or not. - update_size(pid) { - if (this.meta_window_map.has(pid)) { - const meta_window = this.meta_window_map.get(pid); - const blur_actor = meta_window.blur_actor; - if (blur_actor) { - const allocation = this.compute_allocation(meta_window); - blur_actor.x = allocation.x; - blur_actor.y = allocation.y; - blur_actor.width = allocation.width; - blur_actor.height = allocation.height; - } - } else - // the pid was visibly not removed - this.untrack_meta_window(pid); - } - - /// Checks if the given actor needs to be blurred. - /// Accepts only tracked meta window, be it blurred or not. - /// - /// In order to be blurred, a window either: - /// - is whitelisted in the user preferences if not enable-all - /// - is not blacklisted if enable-all - check_blur(meta_window) { - const window_wm_class = meta_window.get_wm_class(); - const enable_all = this.settings.applications.ENABLE_ALL; - const whitelist = this.settings.applications.WHITELIST; - const blacklist = this.settings.applications.BLACKLIST; - if (window_wm_class) - this._log(`pid ${meta_window.bms_pid} associated to wm class name ${window_wm_class}`); - - - // if we are in blacklist mode and the window is not blacklisted - // or if we are in whitelist mode and the window is whitelisted - if ( - window_wm_class !== "" - && ((enable_all && !blacklist.includes(window_wm_class)) - || (!enable_all && whitelist.includes(window_wm_class)) - ) - && [ - Meta.FrameType.NORMAL, - Meta.FrameType.DIALOG, - Meta.FrameType.MODAL_DIALOG - ].includes(meta_window.get_frame_type()) - ) { - // only blur the window if it is not already done - if (!meta_window.blur_actor) - this.create_blur_effect(meta_window); - } - - // remove blur it is not explicitly whitelisted or un-blacklisted - else if (meta_window.blur_actor) - this.remove_blur(meta_window.bms_pid); - } - - /// Add the blur effect to the window. - /// Accepts only tracked meta window that is NOT already blurred. - create_blur_effect(meta_window) { - const pid = meta_window.bms_pid; - const window_actor = meta_window.get_compositor_private(); - - const pipeline = new DummyPipeline(this.effects_manager, this.settings.applications); - let [blur_actor, bg_manager] = pipeline.create_background_with_effect( - window_actor, 'bms-application-blurred-widget' - ); - - meta_window.blur_actor = blur_actor; - meta_window.bg_manager = bg_manager; - - // if hacks are selected, force to repaint the window - if (this.settings.HACKS_LEVEL === 1) { - this._log("hack level 1"); - - this.paint_signals.disconnect_all_for_actor(blur_actor); - this.paint_signals.connect(blur_actor, pipeline.effect); - } else { - this.paint_signals.disconnect_all_for_actor(blur_actor); - } - - // make sure window is blurred in overview - if (this.settings.applications.BLUR_ON_OVERVIEW) - this.enforce_window_visibility_on_overview_for(window_actor); - - // update the size - this.update_size(pid); - - // set the window actor's opacity - this.set_window_opacity(window_actor, this.settings.applications.OPACITY); - - // now set up the signals, for the window actor only: they are disconnected - // in `remove_blur`, whereas the signals for the meta window are disconnected - // only when the whole component is disabled - - // update the window opacity when it changes, else we don't control it fully - this.connections.connect( - window_actor, 'notify::opacity', - _ => { - if (this.focused_window_pid != pid) - this.set_window_opacity(window_actor, this.settings.applications.OPACITY); - } - ); - - // hide the blur if window becomes invisible - if (!window_actor.visible) - blur_actor.hide(); - - this.connections.connect( - window_actor, - 'notify::visible', - window_actor => { - if (window_actor.visible) - meta_window.blur_actor.show(); - else - meta_window.blur_actor.hide(); - } - ); - } - - /// With `focus=true`, tells us we are focused on said window (which can be null if - /// we are not focused anymore). It automatically removes the ancient focus. - /// With `focus=false`, just remove the focus from said window (which can still be null). - set_focus_for_window(meta_window, focus = true) { - let blur_actor = null; - let window_actor = null; - let new_pid = null; - if (meta_window) { - blur_actor = meta_window.blur_actor; - window_actor = meta_window.get_compositor_private(); - new_pid = meta_window.bms_pid; - } - - if (focus) { - // remove old focused window if any - if (this.focused_window_pid) { - const old_focused_window = this.meta_window_map.get(this.focused_window_pid); - if (old_focused_window) - this.set_focus_for_window(old_focused_window, false); - } - // set new focused window pid - this.focused_window_pid = new_pid; - // if we have blur, hide it and make the window opaque - if (this.settings.applications.DYNAMIC_OPACITY && blur_actor) { - blur_actor.hide(); - this.set_window_opacity(window_actor, 255); - } - } - // if we remove the focus and have blur, show it and make the window transparent - else if (blur_actor) { - blur_actor.show(); - this.set_window_opacity(window_actor, this.settings.applications.OPACITY); - } - } - - /// Makes sure that, when the overview is visible, the window actor will - /// stay visible no matter what. - /// We can instead hide the last child of the window actor, which will - /// improve performances without hiding the blur effect. - enforce_window_visibility_on_overview_for(window_actor) { - this.connections.connect(window_actor, 'notify::visible', - _ => { - if (this.settings.applications.BLUR_ON_OVERVIEW) { - if ( - !window_actor.visible - && Main.overview.visible - ) { - window_actor.show(); - window_actor.get_last_child().hide(); - } - else if ( - window_actor.visible - ) - window_actor.get_last_child().show(); - } - } - ); - } - - /// Set the opacity of the window actor that sits on top of the blur effect. - set_window_opacity(window_actor, opacity) { - window_actor?.get_children().forEach(child => { - if (child.name !== "blur-actor" && child.opacity != opacity) - child.opacity = opacity; - }); - } - - /// Update the opacity of all window actors. - set_opacity() { - let opacity = this.settings.applications.OPACITY; - - this.meta_window_map.forEach(((meta_window, pid) => { - if (pid != this.focused_window_pid && meta_window.blur_actor) { - let window_actor = meta_window.get_compositor_private(); - this.set_window_opacity(window_actor, opacity); - } - })); - } - - /// Compute the size and position for a blur actor. - /// If `scale-monitor-framebuffer` experimental feature if on, we don't need to manage scaling. - /// Else, on wayland, we need to divide by the scale to get the correct result. - compute_allocation(meta_window) { - const scale_monitor_framebuffer = this.mutter_gsettings.get_strv('experimental-features') - .includes('scale-monitor-framebuffer'); - const is_wayland = Meta.is_wayland_compositor(); - const monitor_index = meta_window.get_monitor(); - // check if the window is using wayland, or xwayland/xorg for rendering - const scale = !scale_monitor_framebuffer && is_wayland && meta_window.get_client_type() == 0 - ? Main.layoutManager.monitors[monitor_index].geometry_scale - : 1; - - let frame = meta_window.get_frame_rect(); - let buffer = meta_window.get_buffer_rect(); - - return { - x: (frame.x - buffer.x) / scale, - y: (frame.y - buffer.y) / scale, - width: frame.width / scale, - height: frame.height / scale - }; - } - - /// Removes the blur actor to make a blurred window become normal again. - /// It however does not untrack the meta window itself. - /// Accepts a pid corresponding (or not) to a blurred (or not) meta window. - remove_blur(pid) { - this._log(`removing blur for pid ${pid}`); - - let meta_window = this.meta_window_map.get(pid); - if (meta_window) { - let window_actor = meta_window.get_compositor_private(); - let blur_actor = meta_window.blur_actor; - let bg_manager = meta_window.bg_manager; - - if (blur_actor && window_actor) { - // reset the opacity - this.set_window_opacity(window_actor, 255); - - // remove the blurred actor - window_actor.remove_child(blur_actor); - bg_manager._bms_pipeline.destroy(); - bg_manager.destroy(); - blur_actor.destroy(); - - // kinda untrack the blurred actor, as its presence is how we know - // whether we are blurred or not - delete meta_window.blur_actor; - delete meta_window.bg_manager; - - // disconnect the signals of the window actor - this.paint_signals.disconnect_all_for_actor(blur_actor); - this.connections.disconnect_all_for(window_actor); - } - } - } - - /// Kinda the same as `remove_blur`, but better: it also untracks the window. - /// This needs to be called when the component is being disabled, else it - /// would cause havoc by having untracked windows during normal operations, - /// which is not the point at all! - /// Accepts a pid corresponding (or not) to a blurred (or not) meta window. - untrack_meta_window(pid) { - this.remove_blur(pid); - let meta_window = this.meta_window_map.get(pid); - if (meta_window) { - this.connections.disconnect_all_for(meta_window); - this.meta_window_map.delete(pid); - } - } - - disable() { - this._log("removing blur from applications..."); - - this.service?.unexport(); - delete this.mutter_gsettings; - - this.meta_window_map.forEach((_meta_window, pid) => { - this.untrack_meta_window(pid); - }); - - this.connections.disconnect_all(); - this.paint_signals.disconnect_all(); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > applications] ${str}`); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/dash_to_dock.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/dash_to_dock.js deleted file mode 100755 index 4ff212c6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/dash_to_dock.js +++ /dev/null @@ -1,421 +0,0 @@ -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import { PaintSignals } from '../conveniences/paint_signals.js'; - -import { Pipeline } from '../conveniences/pipeline.js'; -import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; - -const DASH_STYLES = [ - "transparent-dash", - "light-dash", - "dark-dash" -]; - - -/// This type of object is created for every dash found, and talks to the main -/// DashBlur thanks to signals. -/// -/// This allows to dynamically track the created dashes for each screen. -class DashInfos { - constructor( - dash_blur, dash, dash_container, dash_background, - background, background_group, bg_manager - ) { - // the parent DashBlur object, to communicate - this.dash_blur = dash_blur; - this.dash = dash; - this.dash_container = dash_container; - this.dash_background = dash_background; - this.background = background; - this.background_group = background_group; - this.bg_manager = bg_manager; - this.settings = dash_blur.settings; - this.old_style = this.dash._background.style; - - this.dash_destroy_id = dash.connect('destroy', () => this.remove_dash_blur(false)); - this.dash_blur_connections_ids = []; - this.dash_blur_connections_ids.push( - this.dash_blur.connect('remove-dashes', () => this.remove_dash_blur()), - this.dash_blur.connect('override-style', () => this.override_style()), - this.dash_blur.connect('remove-style', () => this.remove_style()), - this.dash_blur.connect('show', () => this.background_group.show()), - this.dash_blur.connect('hide', () => this.background_group.hide()), - this.dash_blur.connect('update-size', () => this.update_size()), - this.dash_blur.connect('change-blur-type', () => this.change_blur_type()), - this.dash_blur.connect('update-pipeline', () => this.update_pipeline()) - ); - } - - // IMPORTANT: do never call this in a mutable `this.dash_blur.forEach` - remove_dash_blur(dash_not_already_destroyed = true) { - // remove the style and destroy the effects - this.remove_style(); - this.destroy_dash(dash_not_already_destroyed); - - // remove the dash infos from their list - const dash_infos_index = this.dash_blur.dashes.indexOf(this); - if (dash_infos_index >= 0) - this.dash_blur.dashes.splice(dash_infos_index, 1); - - // disconnect everything - this.dash_blur_connections_ids.forEach(id => { if (id) this.dash_blur.disconnect(id); }); - this.dash_blur_connections_ids = []; - if (this.dash_destroy_id) - this.dash.disconnect(this.dash_destroy_id); - this.dash_destroy_id = null; - } - - override_style() { - this.remove_style(); - - this.dash.set_style_class_name( - DASH_STYLES[this.settings.dash_to_dock.STYLE_DASH_TO_DOCK] - ); - } - - remove_style() { - this.dash._background.style = this.old_style; - - DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) - ); - } - - destroy_dash(dash_not_already_destroyed = true) { - if (!dash_not_already_destroyed) - this.bg_manager.backgroundActor = null; - - this.paint_signals?.disconnect_all(); - this.dash.get_parent().remove_child(this.background_group); - this.bg_manager._bms_pipeline.destroy(); - this.bg_manager.destroy(); - this.background_group.destroy(); - } - - change_blur_type() { - this.destroy_dash(); - - let [ - background, background_group, bg_manager, paint_signals - ] = this.dash_blur.add_blur(this.dash); - - this.background = background; - this.background_group = background_group; - this.bg_manager = bg_manager; - this.paint_signals = paint_signals; - - this.dash.get_parent().insert_child_at_index(this.background_group, 0); - - this.update_size(); - } - - update_pipeline() { - this.bg_manager._bms_pipeline.change_pipeline_to( - this.settings.dash_to_dock.PIPELINE - ); - } - - update_size() { - if (this.dash_blur.is_static) { - let [x, y] = this.get_dash_position(this.dash_container, this.dash_background); - - this.background.x = -x; - this.background.y = -y; - - if (this.dash_container.get_style_class_name().includes("top")) - this.background.set_clip( - x, - y + this.dash.y + this.dash_background.y, - this.dash_background.width, - this.dash_background.height - ); - else if (this.dash_container.get_style_class_name().includes("bottom")) - this.background.set_clip( - x, - y + this.dash.y + this.dash_background.y, - this.dash_background.width, - this.dash_background.height - ); - else if (this.dash_container.get_style_class_name().includes("left")) - this.background.set_clip( - x + this.dash.x + this.dash_background.x, - y + this.dash.y + this.dash_background.y, - this.dash_background.width, - this.dash_background.height - ); - else if (this.dash_container.get_style_class_name().includes("right")) - this.background.set_clip( - x + this.dash.x + this.dash_background.x, - y + this.dash.y + this.dash_background.y, - this.dash_background.width, - this.dash_background.height - ); - } else { - this.background.width = this.dash_background.width; - this.background.height = this.dash_background.height; - - this.background.x = this.dash_background.x; - this.background.y = this.dash_background.y + this.dash.y; - } - } - - get_dash_position(dash_container, dash_background) { - var x, y; - - let monitor = Main.layoutManager.findMonitorForActor(dash_container); - let dash_box = dash_container._slider.get_child(); - - if (dash_container.get_style_class_name().includes("top")) { - x = (monitor.width - dash_background.width) / 2; - y = dash_box.y; - } else if (dash_container.get_style_class_name().includes("bottom")) { - x = (monitor.width - dash_background.width) / 2; - y = monitor.height - dash_container.height; - } else if (dash_container.get_style_class_name().includes("left")) { - x = dash_box.x; - y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y; - } else if (dash_container.get_style_class_name().includes("right")) { - x = monitor.width - dash_container.width; - y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y; - } - - return [x, y]; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > dash] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > dash] ${str}`); - } -} - -export const DashBlur = class DashBlur extends Signals.EventEmitter { - constructor(connections, settings, _) { - super(); - this.dashes = []; - this.connections = connections; - this.settings = settings; - this.paint_signals = new PaintSignals(connections); - this.is_static = this.settings.dash_to_dock.STATIC_BLUR; - this.enabled = false; - } - - enable() { - this.connections.connect(Main.uiGroup, 'child-added', (_, actor) => { - if ( - (actor.get_name() === "dashtodockContainer") && - (actor.constructor.name === 'DashToDock') - ) - this.try_blur(actor); - }); - - this.blur_existing_dashes(); - this.connect_to_overview(); - - this.update_size(); - - this.enabled = true; - } - - // Finds all existing dashes on every monitor, and call `try_blur` on them - // We cannot only blur `Main.overview.dash`, as there could be several - blur_existing_dashes() { - this._log("searching for dash"); - - // blur every dash found, filtered by name - Main.uiGroup.get_children().filter((child) => { - return (child.get_name() === "dashtodockContainer") && - (child.constructor.name === 'DashToDock'); - }).forEach(dash_container => this.try_blur(dash_container)); - } - - // Tries to blur the dash contained in the given actor - try_blur(dash_container) { - let dash_box = dash_container._slider.get_child(); - - // verify that we did not already blur that dash - if (!dash_box.get_children().some(child => - child.get_name() === "bms-dash-backgroundgroup" - )) { - this._log("dash to dock found, blurring it"); - - // finally blur the dash - let dash = dash_box.get_children().find(child => { - return child.get_name() === 'dash'; - }); - - this.dashes.push(this.blur_dash_from(dash, dash_container)); - } - } - - // Blurs the dash and returns a `DashInfos` containing its information - blur_dash_from(dash, dash_container) { - let [background, background_group, bg_manager, paint_signals] = this.add_blur(dash); - - // insert the background group to the right element - dash.get_parent().insert_child_at_index(background_group, 0); - - // updates size and position on change - this.connections.connect( - dash, - ['notify::width', 'notify::height'], - _ => this.update_size() - ); - this.connections.connect( - dash_container, - ['notify::width', 'notify::height', 'notify::y', 'notify::x'], - _ => this.update_size() - ); - - const dash_background = dash.get_children().find(child => { - return child.get_style_class_name() === 'dash-background'; - }); - - // create infos - let infos = new DashInfos( - this, - dash, - dash_container, - dash_background, - background, - background_group, - bg_manager, - paint_signals - ); - - this.update_size(); - this.update_background(); - - // returns infos - return infos; - } - - add_blur(dash) { - const monitor = Main.layoutManager.findMonitorForActor(dash); - if (!monitor) - return; - - const background_group = new Meta.BackgroundGroup({ - name: 'bms-dash-backgroundgroup', width: 0, height: 0 - }); - - let background, bg_manager, paint_signals; - let static_blur = this.settings.dash_to_dock.STATIC_BLUR; - if (static_blur) { - let bg_manager_list = []; - const pipeline = new Pipeline( - global.blur_my_shell._effects_manager, - global.blur_my_shell._pipelines_manager, - this.settings.dash_to_dock.PIPELINE - ); - background = pipeline.create_background_with_effects( - monitor.index, bg_manager_list, - background_group, 'bms-dash-blurred-widget' - ); - bg_manager = bg_manager_list[0]; - } - else { - const pipeline = new DummyPipeline( - global.blur_my_shell._effects_manager, - this.settings.dash_to_dock - ); - [background, bg_manager] = pipeline.create_background_with_effect( - background_group, 'bms-dash-blurred-widget' - ); - - paint_signals = new PaintSignals(this.connections); - - // HACK - // - //`Shell.BlurEffect` does not repaint when shadows are under it. [1] - // - // This does not entirely fix this bug (shadows caused by windows - // still cause artifacts), but it prevents the shadows of the dash - // buttons to cause artifacts on the dash itself - // - // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857 - - if (this.settings.HACKS_LEVEL === 1) { - this._log("hack level 1"); - - paint_signals.disconnect_all(); - paint_signals.connect(background, pipeline.effect); - } else { - paint_signals.disconnect_all(); - } - } - - return [background, background_group, bg_manager, paint_signals]; - } - - change_blur_type() { - this.is_static = this.settings.dash_to_dock.STATIC_BLUR; - this.emit('change-blur-type'); - - this.update_background(); - } - - /// Connect when overview if opened/closed to hide/show the blur accordingly - connect_to_overview() { - this.connections.disconnect_all_for(Main.overview); - - if (this.settings.dash_to_dock.UNBLUR_IN_OVERVIEW) { - this.connections.connect( - Main.overview, 'showing', _ => this.hide() - ); - this.connections.connect( - Main.overview, 'hidden', _ => this.show() - ); - } - }; - - /// Updates the background to either remove it or not, according to the - /// user preferences. - update_background() { - this._log("updating background"); - if (this.settings.dash_to_dock.OVERRIDE_BACKGROUND) - this.emit('override-style'); - else - this.emit('remove-style'); - } - - update_pipeline() { - this.emit('update-pipeline'); - } - - update_size() { - this.emit('update-size'); - } - - show() { - this.emit('show'); - } - hide() { - this.emit('hide'); - } - - disable() { - this._log("removing blur from dashes"); - - this.emit('remove-dashes'); - - this.dashes = []; - this.connections.disconnect_all(); - - this.enabled = false; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > dash manager] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > dash manager] ${str}`); - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/lockscreen.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/lockscreen.js deleted file mode 100755 index 7755ba9c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/lockscreen.js +++ /dev/null @@ -1,89 +0,0 @@ -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import { UnlockDialog } from 'resource:///org/gnome/shell/ui/unlockDialog.js'; - -import { Pipeline } from '../conveniences/pipeline.js'; - -const original_createBackground = - UnlockDialog.prototype._createBackground; -const original_updateBackgroundEffects = - UnlockDialog.prototype._updateBackgroundEffects; -const original_updateBackgrounds = - UnlockDialog.prototype._updateBackgrounds; - - -export const LockscreenBlur = class LockscreenBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.settings = settings; - this.effects_manager = effects_manager; - this.enabled = false; - } - - enable() { - this._log("blurring lockscreen"); - - this.update_lockscreen(); - - this.enabled = true; - } - - update_lockscreen() { - UnlockDialog.prototype._createBackground = - this._createBackground; - UnlockDialog.prototype._updateBackgroundEffects = - this._updateBackgroundEffects; - UnlockDialog.prototype._updateBackgrounds = - this._updateBackgrounds; - } - - _createBackground(monitor_index) { - let pipeline = new Pipeline( - global.blur_my_shell._effects_manager, global.blur_my_shell._pipelines_manager, - global.blur_my_shell._settings.lockscreen.PIPELINE - ); - - pipeline.create_background_with_effects( - monitor_index, - this._bgManagers, - this._backgroundGroup, - "screen-shield-background" - ); - } - - _updateBackgroundEffects() { - this._updateBackgrounds(); - } - - _updateBackgrounds() { - for (let i = 0; i < this._bgManagers.length; i++) { - this._bgManagers[i]._bms_pipeline.destroy(); - this._bgManagers[i].destroy(); - } - - this._bgManagers = []; - this._backgroundGroup.destroy_all_children(); - - for (let i = 0; i < Main.layoutManager.monitors.length; i++) - this._createBackground(i); - } - - disable() { - this._log("removing blur from lockscreen"); - - UnlockDialog.prototype._createBackground = - original_createBackground; - UnlockDialog.prototype._updateBackgroundEffects = - original_updateBackgroundEffects; - UnlockDialog.prototype._updateBackgrounds = - original_updateBackgrounds; - - this.connections.disconnect_all(); - - this.enabled = false; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > lockscreen] ${str}`); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/overview.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/overview.js deleted file mode 100755 index b09dcda1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/overview.js +++ /dev/null @@ -1,209 +0,0 @@ -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { WorkspaceAnimationController } from 'resource:///org/gnome/shell/ui/workspaceAnimation.js'; -const wac_proto = WorkspaceAnimationController.prototype; - -import { Pipeline } from '../conveniences/pipeline.js'; - -const OVERVIEW_COMPONENTS_STYLE = [ - "overview-components-light", - "overview-components-dark", - "overview-components-transparent" -]; - - -export const OverviewBlur = class OverviewBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.settings = settings; - this.effects_manager = effects_manager; - this.overview_background_managers = []; - this.overview_background_group = new Meta.BackgroundGroup( - { name: 'bms-overview-backgroundgroup' } - ); - this.animation_background_managers = []; - this.animation_background_group = new Meta.BackgroundGroup( - { name: 'bms-animation-backgroundgroup' } - ); - this.enabled = false; - } - - enable() { - this._log("blurring overview"); - - // add css class name for workspace-switch background - Main.uiGroup.add_style_class_name("blurred-overview"); - - // add css class name to make components semi-transparent if wanted - this.update_components_classname(); - - // update backgrounds when the component is enabled - this.update_backgrounds(); - - // connect to monitors change - this.connections.connect(Main.layoutManager, 'monitors-changed', - _ => this.update_backgrounds() - ); - - // part for the workspace animation switch - - // make sure not to do this part if the extension was enabled prior, as - // the functions would call themselves and cause infinite recursion - if (!this.enabled) { - // store original workspace switching methods for restoring them on - // disable() - this._original_PrepareSwitch = wac_proto._prepareWorkspaceSwitch; - this._original_FinishSwitch = wac_proto._finishWorkspaceSwitch; - - const w_m = global.workspace_manager; - const outer_this = this; - - // create a blurred background actor for each monitor during a - // workspace switch - wac_proto._prepareWorkspaceSwitch = function (...params) { - outer_this._log("prepare workspace switch"); - outer_this._original_PrepareSwitch.apply(this, params); - - // this permits to show the blur behind windows that are on - // workspaces on the left and right - if ( - outer_this.settings.applications.BLUR - ) { - let ws_index = w_m.get_active_workspace_index(); - [ws_index - 1, ws_index + 1].forEach( - i => w_m.get_workspace_by_index(i)?.list_windows().forEach( - window => window.get_compositor_private().show() - ) - ); - } - - Main.uiGroup.insert_child_above( - outer_this.animation_background_group, - global.window_group - ); - - outer_this.animation_background_managers.forEach(bg_manager => { - if (bg_manager._bms_pipeline.actor) - if ( - Meta.prefs_get_workspaces_only_on_primary() && - bg_manager._monitorIndex !== Main.layoutManager.primaryMonitor.index - ) - bg_manager._bms_pipeline.actor.visible = false; - else - bg_manager._bms_pipeline.actor.visible = true; - }); - }; - - // remove the workspace-switch actors when the switch is done - wac_proto._finishWorkspaceSwitch = function (...params) { - outer_this._log("finish workspace switch"); - outer_this._original_FinishSwitch.apply(this, params); - - // this hides windows that are not on the current workspace - if ( - outer_this.settings.applications.BLUR - ) - for (let i = 0; i < w_m.get_n_workspaces(); i++) { - if (i != w_m.get_active_workspace_index()) - w_m.get_workspace_by_index(i)?.list_windows().forEach( - window => window.get_compositor_private().hide() - ); - } - - Main.uiGroup.remove_child(outer_this.animation_background_group); - }; - } - - this.enabled = true; - } - - update_backgrounds() { - // remove every old background - this.remove_background_actors(); - // create new backgrounds for the overview and the animation - for (let i = 0; i < Main.layoutManager.monitors.length; i++) { - const pipeline_overview = new Pipeline( - this.effects_manager, - global.blur_my_shell._pipelines_manager, - this.settings.overview.PIPELINE - ); - pipeline_overview.create_background_with_effects( - i, this.overview_background_managers, - this.overview_background_group, 'bms-overview-blurred-widget' - ); - - const pipeline_animation = new Pipeline( - this.effects_manager, - global.blur_my_shell._pipelines_manager, - this.settings.overview.PIPELINE - ); - pipeline_animation.create_background_with_effects( - i, this.animation_background_managers, - this.animation_background_group, 'bms-animation-blurred-widget' - ); - } - // add the container widget for the overview only to the overview group - Main.layoutManager.overviewGroup.insert_child_at_index(this.overview_background_group, 0); - } - - /// Updates the classname to style overview components with semi-transparent - /// backgrounds. - update_components_classname() { - OVERVIEW_COMPONENTS_STYLE.forEach( - style => Main.uiGroup.remove_style_class_name(style) - ); - - if (this.settings.overview.STYLE_COMPONENTS > 0) - Main.uiGroup.add_style_class_name( - OVERVIEW_COMPONENTS_STYLE[this.settings.overview.STYLE_COMPONENTS - 1] - ); - } - - remove_background_actors() { - this.overview_background_group.remove_all_children(); - this.animation_background_group.remove_all_children(); - this.overview_background_managers.forEach(background_manager => { - background_manager._bms_pipeline.destroy(); - background_manager.destroy(); - }); - this.animation_background_managers.forEach(background_manager => { - background_manager._bms_pipeline.destroy(); - background_manager.destroy(); - }); - this.overview_background_managers = []; - this.animation_background_managers = []; - } - - disable() { - this._log("removing blur from overview"); - - this.remove_background_actors(); - Main.uiGroup.remove_style_class_name("blurred-overview"); - OVERVIEW_COMPONENTS_STYLE.forEach( - style => Main.uiGroup.remove_style_class_name(style) - ); - - // make sure to absolutely not do this if the component was not enabled - // prior, as this would cause infinite recursion - if (this.enabled) { - // restore original behavior - if (this._original_PrepareSwitch) - wac_proto._prepareWorkspaceSwitch = this._original_PrepareSwitch; - if (this._original_FinishSwitch) - wac_proto._finishWorkspaceSwitch = this._original_FinishSwitch; - } - - this.connections.disconnect_all(); - this.enabled = false; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > overview] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > overview] ${str}`); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/panel.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/panel.js deleted file mode 100755 index ae616f3f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/panel.js +++ /dev/null @@ -1,542 +0,0 @@ -import St from 'gi://St'; -import Meta from 'gi://Meta'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../conveniences/paint_signals.js'; - -import { Pipeline } from '../conveniences/pipeline.js'; -import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; - -const DASH_TO_PANEL_UUID = 'dash-to-panel@jderose9.github.com'; -const PANEL_STYLES = [ - "transparent-panel", - "light-panel", - "dark-panel", - "contrasted-panel" -]; - - -export const PanelBlur = class PanelBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.window_signal_ids = new Map(); - this.settings = settings; - this.effects_manager = effects_manager; - this.actors_list = []; - this.enabled = false; - } - - enable() { - this._log("blurring top panel"); - - // check for panels when Dash to Panel is activated - this.connections.connect( - Main.extensionManager, - 'extension-state-changed', - (_, extension) => { - if (extension.uuid === DASH_TO_PANEL_UUID - && extension.state === 1 - ) { - this.connections.connect( - global.dashToPanel, - 'panels-created', - _ => this.blur_dtp_panels() - ); - - this.blur_existing_panels(); - } - } - ); - - this.blur_existing_panels(); - - // connect to overview being opened/closed, and dynamically show or not - // the blur when a window is near a panel - this.connect_to_windows_and_overview(); - - // update the classname if the panel to have or have not light text - this.update_light_text_classname(); - - // connect to monitors change - this.connections.connect(Main.layoutManager, 'monitors-changed', - _ => this.reset() - ); - - this.enabled = true; - } - - reset() { - this._log("resetting..."); - - this.disable(); - setTimeout(_ => this.enable(), 1); - } - - /// Check for already existing panels and blur them if they are not already - blur_existing_panels() { - // check if dash-to-panel is present - if (global.dashToPanel) { - // blur already existing ones - if (global.dashToPanel.panels) - this.blur_dtp_panels(); - } else { - // if no dash-to-panel, blur the main and only panel - this.maybe_blur_panel(Main.panel); - } - } - - blur_dtp_panels() { - // FIXME when Dash to Panel changes its size, it seems it creates new - // panels; but I can't get to delete old widgets - - // blur every panel found - global.dashToPanel.panels.forEach(p => { - this.maybe_blur_panel(p.panel); - }); - - // if main panel is not included in the previous panels, blur it - if ( - !global.dashToPanel.panels - .map(p => p.panel) - .includes(Main.panel) - && - this.settings.dash_to_panel.BLUR_ORIGINAL_PANEL - ) - this.maybe_blur_panel(Main.panel); - }; - - /// Blur a panel only if it is not already blurred (contained in the list) - maybe_blur_panel(panel) { - // check if the panel is contained in the list - let actors = this.actors_list.find( - actors => actors.widgets.panel == panel - ); - - if (!actors) - // if the actors is not blurred, blur it - this.blur_panel(panel); - } - - /// Blur a panel - blur_panel(panel) { - let panel_box = panel.get_parent(); - let is_dtp_panel = false; - if (!panel_box.name) { - is_dtp_panel = true; - panel_box = panel_box.get_parent(); - } - - let monitor = Main.layoutManager.findMonitorForActor(panel); - if (!monitor) - return; - - let background_group = new Meta.BackgroundGroup( - { name: 'bms-panel-backgroundgroup', width: 0, height: 0 } - ); - - let background, bg_manager; - let static_blur = this.settings.panel.STATIC_BLUR; - if (static_blur) { - let bg_manager_list = []; - const pipeline = new Pipeline( - this.effects_manager, - global.blur_my_shell._pipelines_manager, - this.settings.panel.PIPELINE - ); - background = pipeline.create_background_with_effects( - monitor.index, bg_manager_list, - background_group, 'bms-panel-blurred-widget' - ); - bg_manager = bg_manager_list[0]; - } - else { - const pipeline = new DummyPipeline(this.effects_manager, this.settings.panel); - [background, bg_manager] = pipeline.create_background_with_effect( - background_group, 'bms-panel-blurred-widget' - ); - - let paint_signals = new PaintSignals(this.connections); - - // HACK - // - //`Shell.BlurEffect` does not repaint when shadows are under it. [1] - // - // This does not entirely fix this bug (shadows caused by windows - // still cause artifacts), but it prevents the shadows of the panel - // buttons to cause artifacts on the panel itself - // - // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857 - - { - if (this.settings.HACKS_LEVEL === 1) { - this._log("panel hack level 1"); - - paint_signals.disconnect_all(); - paint_signals.connect(background, pipeline.effect); - } else { - paint_signals.disconnect_all(); - } - } - } - - // insert the background group to the panel box - panel_box.insert_child_at_index(background_group, 0); - - // the object that is used to remembering each elements that is linked to the blur effect - let actors = { - widgets: { panel, panel_box, background, background_group }, - static_blur, - monitor, - bg_manager, - is_dtp_panel - }; - this.actors_list.push(actors); - - // update the size of the actor - this.update_size(actors); - - // connect to panel, panel_box and its parent position or size change - // this should fire update_size every time one of its params change - this.connections.connect( - panel, - 'notify::position', - _ => this.update_size(actors) - ); - this.connections.connect( - panel_box, - ['notify::size', 'notify::position'], - _ => this.update_size(actors) - ); - this.connections.connect( - panel_box.get_parent(), - 'notify::position', - _ => this.update_size(actors) - ); - - // connect to the panel getting destroyed - this.connections.connect( - panel, - 'destroy', - _ => this.destroy_blur(actors, true) - ); - } - - update_size(actors) { - let panel = actors.widgets.panel; - let panel_box = actors.widgets.panel_box; - let background = actors.widgets.background; - let monitor = Main.layoutManager.findMonitorForActor(panel); - if (!monitor) - return; - - let [width, height] = panel_box.get_size(); - - // if static blur, need to clip the background - if (actors.static_blur) { - // an alternative to panel.get_transformed_position, because it - // sometimes yields NaN (probably when the actor is not fully - // positionned yet) - let [p_x, p_y] = panel_box.get_position(); - let [p_p_x, p_p_y] = panel_box.get_parent().get_position(); - let x = p_x + p_p_x - monitor.x; - let y = p_y + p_p_y - monitor.y; - - background.set_clip(x, y, width, height); - background.x = -x; - background.y = -y; - } else { - background.x = panel.x; - background.y = panel.y; - background.width = width; - background.height = height; - } - - // update the monitor panel is on - actors.monitor = Main.layoutManager.findMonitorForActor(panel); - } - - /// Connect when overview if opened/closed to hide/show the blur accordingly - /// - /// If HIDETOPBAR is set, we need just to hide the blur when showing appgrid - /// (so no shadow is cropped) - connect_to_overview() { - // may be called when panel blur is disabled, if hidetopbar - // compatibility is toggled on/off - // if this is the case, do nothing as only the panel blur interfers with - // hidetopbar - if ( - this.settings.panel.BLUR && - this.settings.panel.UNBLUR_IN_OVERVIEW - ) { - if (!this.settings.hidetopbar.COMPATIBILITY) { - this.connections.connect( - Main.overview, 'showing', _ => this.hide() - ); - this.connections.connect( - Main.overview, 'hidden', _ => this.show() - ); - } else { - let appDisplay = Main.overview._overview._controls._appDisplay; - - this.connections.connect( - appDisplay, 'show', _ => this.hide() - ); - this.connections.connect( - appDisplay, 'hide', _ => this.show() - ); - this.connections.connect( - Main.overview, 'hidden', _ => this.show() - ); - } - - } - } - - /// Connect to windows disable transparency when a window is too close - connect_to_windows() { - if ( - this.settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY - ) { - // connect to overview opening/closing - this.connections.connect(Main.overview, ['showing', 'hiding'], - _ => this.update_visibility() - ); - - // connect to session mode update - this.connections.connect(Main.sessionMode, 'updated', - _ => this.update_visibility() - ); - - // manage already-existing windows - for (const meta_window_actor of global.get_window_actors()) { - this.on_window_actor_added( - meta_window_actor.get_parent(), meta_window_actor - ); - } - - // manage windows at their creation/removal - this.connections.connect(global.window_group, 'child-added', - this.on_window_actor_added.bind(this) - ); - this.connections.connect(global.window_group, 'child-removed', - this.on_window_actor_removed.bind(this) - ); - - // connect to a workspace change - this.connections.connect(global.window_manager, 'switch-workspace', - _ => this.update_visibility() - ); - - // perform early update - this.update_visibility(); - } else { - // reset transparency for every panels - this.actors_list.forEach( - actors => this.set_should_override_panel(actors, true) - ); - } - } - - /// An helper to connect to both the windows and overview signals. - /// This is the only function that should be directly called, to prevent - /// inconsistencies with signals not being disconnected. - connect_to_windows_and_overview() { - this.disconnect_from_windows_and_overview(); - this.connect_to_overview(); - this.connect_to_windows(); - } - - /// Disconnect all the connections created by connect_to_windows - disconnect_from_windows_and_overview() { - // disconnect the connections to actors - for (const actor of [ - Main.overview, Main.sessionMode, - global.window_group, global.window_manager, - Main.overview._overview._controls._appDisplay - ]) { - this.connections.disconnect_all_for(actor); - } - - // disconnect the connections from windows - for (const [actor, ids] of this.window_signal_ids) { - for (const id of ids) { - actor.disconnect(id); - } - } - this.window_signal_ids = new Map(); - } - - /// Update the css classname of the panel for light theme - update_light_text_classname(disable = false) { - if (this.settings.panel.FORCE_LIGHT_TEXT && !disable) - Main.panel.add_style_class_name("panel-light-text"); - else - Main.panel.remove_style_class_name("panel-light-text"); - } - - /// Callback when a new window is added - on_window_actor_added(container, meta_window_actor) { - this.window_signal_ids.set(meta_window_actor, [ - meta_window_actor.connect('notify::allocation', - _ => this.update_visibility() - ), - meta_window_actor.connect('notify::visible', - _ => this.update_visibility() - ) - ]); - this.update_visibility(); - } - - /// Callback when a window is removed - on_window_actor_removed(container, meta_window_actor) { - for (const signalId of this.window_signal_ids.get(meta_window_actor)) { - meta_window_actor.disconnect(signalId); - } - this.window_signal_ids.delete(meta_window_actor); - this.update_visibility(); - } - - /// Update the visibility of the blur effect - update_visibility() { - if ( - Main.panel.has_style_pseudo_class('overview') - || !Main.sessionMode.hasWindows - ) { - this.actors_list.forEach( - actors => this.set_should_override_panel(actors, true) - ); - return; - } - - if (!Main.layoutManager.primaryMonitor) - return; - - // get all the windows in the active workspace that are visible - const workspace = global.workspace_manager.get_active_workspace(); - const windows = workspace.list_windows().filter(meta_window => - meta_window.showing_on_its_workspace() - && !meta_window.is_hidden() - && meta_window.get_window_type() !== Meta.WindowType.DESKTOP - // exclude Desktop Icons NG - && meta_window.get_gtk_application_id() !== "com.rastersoft.ding" - && meta_window.get_gtk_application_id() !== "com.desktop.ding" - ); - - // check if at least one window is near enough to each panel and act - // accordingly - const scale = St.ThemeContext.get_for_stage(global.stage).scale_factor; - this.actors_list - // do not apply for dtp panels, as it would only cause bugs and it - // can be done from its preferences anyway - .filter(actors => !actors.is_dtp_panel) - .forEach(actors => { - let panel = actors.widgets.panel; - let panel_top = panel.get_transformed_position()[1]; - let panel_bottom = panel_top + panel.get_height(); - - // check if at least a window is near enough the panel - let window_overlap_panel = false; - windows.forEach(meta_window => { - let window_monitor_i = meta_window.get_monitor(); - let same_monitor = actors.monitor.index == window_monitor_i; - - let window_vertical_pos = meta_window.get_frame_rect().y; - - // if so, and if in the same monitor, then it overlaps - if (same_monitor - && - window_vertical_pos < panel_bottom + 5 * scale - ) - window_overlap_panel = true; - }); - - // if no window overlaps, then the panel is transparent - this.set_should_override_panel( - actors, !window_overlap_panel - ); - }); - } - - /// Choose wether or not the panel background should be overriden, in - /// respect to its argument and the `override-background` setting. - set_should_override_panel(actors, should_override) { - let panel = actors.widgets.panel; - - PANEL_STYLES.forEach(style => panel.remove_style_class_name(style)); - - if ( - this.settings.panel.OVERRIDE_BACKGROUND - && - should_override - ) - panel.add_style_class_name( - PANEL_STYLES[this.settings.panel.STYLE_PANEL] - ); - } - - update_pipeline() { - this.actors_list.forEach(actors => - actors.bg_manager._bms_pipeline.change_pipeline_to( - this.settings.panel.PIPELINE - ) - ); - } - - show() { - this.actors_list.forEach(actors => { - actors.widgets.background.show(); - }); - } - - hide() { - this.actors_list.forEach(actors => { - actors.widgets.background.hide(); - }); - } - - // IMPORTANT: do never call this in a mutable `this.actors_list.forEach` - destroy_blur(actors, panel_already_destroyed) { - this.set_should_override_panel(actors, false); - - actors.bg_manager._bms_pipeline.destroy(); - - if (panel_already_destroyed) - actors.bg_manager.backgroundActor = null; - actors.bg_manager.destroy(); - - if (!panel_already_destroyed) { - actors.widgets.panel_box.remove_child(actors.widgets.background_group); - actors.widgets.background_group.destroy_all_children(); - actors.widgets.background_group.destroy(); - } - - let index = this.actors_list.indexOf(actors); - if (index >= 0) - this.actors_list.splice(index, 1); - } - - disable() { - this._log("removing blur from top panel"); - - this.disconnect_from_windows_and_overview(); - - this.update_light_text_classname(true); - - const immutable_actors_list = [...this.actors_list]; - immutable_actors_list.forEach(actors => this.destroy_blur(actors, false)); - this.actors_list = []; - - this.connections.disconnect_all(); - - this.enabled = false; - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > panel] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > panel] ${str}`); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/screenshot.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/screenshot.js deleted file mode 100755 index c815d07b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/screenshot.js +++ /dev/null @@ -1,110 +0,0 @@ -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { Pipeline } from '../conveniences/pipeline.js'; - -export const ScreenshotBlur = class ScreenshotBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.settings = settings; - this.screenshot_background_managers = []; - this.effects_manager = effects_manager; - } - - enable() { - this._log("blurring screenshot's window selector"); - - // connect to monitors change - this.connections.connect(Main.layoutManager, 'monitors-changed', - _ => this.update_backgrounds() - ); - - // update backgrounds when the component is enabled - this.update_backgrounds(); - } - - update_backgrounds() { - // remove every old background - this.remove_background_actors(); - // create new backgrounds for the screenshot window selector - for (let i = 0; i < Main.screenshotUI._windowSelectors.length; i++) { - const window_selector = Main.screenshotUI._windowSelectors[i]; - const pipeline = new Pipeline( - this.effects_manager, - global.blur_my_shell._pipelines_manager, - this.settings.screenshot.PIPELINE - ); - pipeline.create_background_with_effects( - window_selector._monitorIndex, this.screenshot_background_managers, - window_selector, 'bms-screenshot-blurred-widget' - ); - - // prevent old `BackgroundActor` from being accessed, which creates a whole bug of logs - this.connections.connect(window_selector.get_parent(), 'destroy', _ => { - this.screenshot_background_managers.forEach(background_manager => { - if (background_manager.backgroundActor) { - let widget = background_manager.backgroundActor.get_parent(); - let parent = widget?.get_parent(); - - if (parent == window_selector) { - background_manager._bms_pipeline.destroy(); - parent.remove_child(widget); - } - } - background_manager.destroy(); - }); - - window_selector.get_children().forEach(child => { - if (child.get_name() == 'bms-screenshot-blurred-widget') - window_selector.remove_child(child); - }); - - let index = this.screenshot_background_managers.indexOf(window_selector); - this.screenshot_background_managers.splice(index, 1); - }); - } - } - - update_pipeline() { - this.screenshot_background_managers.forEach(background_manager => - background_manager._bms_pipeline.change_pipeline_to( - this.settings.screenshot.PIPELINE - ) - ); - } - - remove_background_actors() { - this.screenshot_background_managers.forEach(background_manager => { - background_manager._bms_pipeline.destroy(); - if (background_manager.backgroundActor) { - let widget = background_manager.backgroundActor.get_parent(); - widget?.get_parent()?.remove_child(widget); - } - background_manager.destroy(); - }); - - Main.screenshotUI._windowSelectors.forEach(window_selector => - window_selector.get_children().forEach(child => { - if (child.get_name() == 'bms-screenshot-blurred-widget') - window_selector.remove_child(child); - }) - ); - - this.screenshot_background_managers = []; - } - - disable() { - this._log("removing blur from screenshot's window selector"); - - this.remove_background_actors(); - this.connections.disconnect_all(); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > screenshot] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > screenshot] ${str}`); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/window_list.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/window_list.js deleted file mode 100755 index 6ab0644f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/components/window_list.js +++ /dev/null @@ -1,148 +0,0 @@ -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { PaintSignals } from '../conveniences/paint_signals.js'; -import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; - - -export const WindowListBlur = class WindowListBlur { - constructor(connections, settings, effects_manager) { - this.connections = connections; - this.settings = settings; - this.paint_signals = new PaintSignals(connections); - this.effects_manager = effects_manager; - this.pipelines = []; - } - - enable() { - this._log("blurring window list"); - - // blur if window-list is found - Main.layoutManager.uiGroup.get_children().forEach( - child => this.try_blur(child) - ); - - // listen to new actors in `Main.layoutManager.uiGroup` and blur it if - // if is window-list - this.connections.connect( - Main.layoutManager.uiGroup, - 'child-added', - (_, child) => this.try_blur(child) - ); - - // connect to overview - this.connections.connect(Main.overview, 'showing', _ => { - this.hide(); - }); - this.connections.connect(Main.overview, 'hidden', _ => { - this.show(); - }); - } - - try_blur(actor) { - if ( - actor.constructor.name === "WindowList" && - actor.style !== "background:transparent;" - ) { - this._log("found window list to blur"); - - const pipeline = new DummyPipeline( - this.effects_manager, this.settings.window_list - ); - pipeline.attach_effect_to_actor(actor); - this.pipelines.push(pipeline); - - actor.set_style("background:transparent;"); - - actor._windowList.get_children().forEach( - window => this.style_window_button(window) - ); - - this.connections.connect( - actor._windowList, - 'child-added', - (_, window) => this.style_window_button(window) - ); - - this.connections.connect( - actor, - 'destroy', - _ => this.destroy_blur(pipeline, true) - ); - - - // HACK - // - //`Shell.BlurEffect` does not repaint when shadows are under it. [1] - // - // This does not entirely fix this bug (shadows caused by windows - // still cause artifacts), but it prevents the shadows of the panel - // buttons to cause artifacts on the panel itself - // - // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857 - - if (this.settings.HACKS_LEVEL === 1) { - this._log("window list hack level 1"); - - this.paint_signals.disconnect_all_for_actor(actor); - this.paint_signals.connect(actor, pipeline.effect); - } else { - this.paint_signals.disconnect_all_for_actor(actor); - } - } - } - - style_window_button(window) { - window.get_child_at_index(0).set_style( - "box-shadow:none; background-color:rgba(0,0,0,0.2); border-radius:5px;" - ); - } - - // IMPORTANT: do never call this in a mutable `this.pipelines.forEach` - destroy_blur(pipeline, actor_destroyed = false) { - if (!actor_destroyed) { - this.remove_style(pipeline.actor); - this.paint_signals.disconnect_all_for_actor(pipeline.actor); - } - - pipeline.destroy(); - - let index = this.pipelines.indexOf(pipeline); - if (index >= 0) - this.pipelines.splice(pipeline, 1); - } - - remove_style(actor) { - if ( - actor.constructor.name === "WindowList" && - actor.style === "background:transparent;" - ) { - actor.style = null; - actor._windowList.get_children().forEach( - child => child.get_child_at_index(0).set_style(null) - ); - } - } - - hide() { - this.pipelines.forEach(pipeline => pipeline.effect?.set_enabled(false)); - } - - show() { - this.pipelines.forEach(pipeline => pipeline.effect?.set_enabled(true)); - } - - disable() { - this._log("removing blur from window list"); - - const immutable_pipelines_list = [...this.pipelines]; - immutable_pipelines_list.forEach(pipeline => this.destroy_blur(pipeline)); - - this.pipelines = []; - this.connections.disconnect_all(); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > window list] ${str}`); - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/connections.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/connections.js deleted file mode 100755 index 0583db33..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/connections.js +++ /dev/null @@ -1,106 +0,0 @@ -import GObject from 'gi://GObject'; - -/// An object to easily manage signals. -export const Connections = class Connections { - constructor() { - this.buffer = []; - } - - /// Adds a connection. - /// - /// Takes as arguments: - /// - an actor, which fires the signal - /// - signal(s) (string or array of strings), which are watched for - /// - a callback, which is called when the signal is fired - connect(actor, signals, handler) { - if (signals instanceof Array) { - signals.forEach(signal => { - let id = actor.connect(signal, handler); - this.process_connection(actor, id); - }); - } else { - let id = actor.connect(signals, handler); - this.process_connection(actor, id); - } - - } - - /// Process the given actor and id. - /// - /// This makes sure that the signal is disconnected when the actor is - /// destroyed, and that the signal can be managed through other Connections - /// methods. - process_connection(actor, id) { - let infos = { - actor: actor, - id: id - }; - - // remove the signal when the actor is destroyed - if ( - actor.connect && - ( - !(actor instanceof GObject.Object) || - GObject.signal_lookup('destroy', actor) - ) - ) { - let destroy_id = actor.connect('destroy', () => { - actor.disconnect(id); - actor.disconnect(destroy_id); - - let index = this.buffer.indexOf(infos); - if (index >= 0) { - this.buffer.splice(index, 1); - } - }); - infos.destroy_id = destroy_id; - } - - this.buffer.push(infos); - } - - /// Disconnects every connection found for an actor. - disconnect_all_for(actor) { - // get every connection stored for the actor - let actor_connections = this.buffer.filter( - infos => infos.actor === actor - ); - - // remove each of them - actor_connections.forEach(connection => { - // disconnect - try { - connection.actor.disconnect(connection.id); - if ('destroy_id' in connection) - connection.actor.disconnect(connection.destroy_id); - } catch (e) { - this._warn(`error removing connection: ${e}; continuing`); - } - - // remove from buffer - let index = this.buffer.indexOf(connection); - this.buffer.splice(index, 1); - }); - } - - /// Disconnect every connection for each actor. - disconnect_all() { - this.buffer.forEach(connection => { - // disconnect - try { - connection.actor.disconnect(connection.id); - if ('destroy_id' in connection) - connection.actor.disconnect(connection.destroy_id); - } catch (e) { - this._warn(`error removing connection: ${e}; continuing`); - } - }); - - // reset buffer - this.buffer = []; - } - - _warn(str) { - console.warn(`[Blur my Shell > connections] ${str}`); - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/dummy_pipeline.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/dummy_pipeline.js deleted file mode 100755 index c0d2a70a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/dummy_pipeline.js +++ /dev/null @@ -1,96 +0,0 @@ -import St from 'gi://St'; -import Clutter from 'gi://Clutter'; - -/// A dummy `Pipeline`, for dynamic blur only. -/// Instead of a pipeline id, we take the settings of the component we want to blur. -export const DummyPipeline = class DummyPipeline { - constructor(effects_manager, settings, actor = null) { - this.effects_manager = effects_manager; - this.settings = settings; - this.effect = null; - this.attach_effect_to_actor(actor); - } - - create_background_with_effect( - background_group, - widget_name - ) { - // create the new actor - this.actor = new St.Widget({ name: widget_name }); - - this.attach_effect_to_actor(this.actor); - - // a dummy `BackgroundManager`, just to access the pipeline easily - let bg_manager = new Clutter.Actor; - bg_manager.backgroundActor = this.actor; - bg_manager._bms_pipeline = this; - - background_group.insert_child_at_index(this.actor, 0); - - return [this.actor, bg_manager]; - }; - - attach_effect_to_actor(actor) { - // set the actor - this.actor = actor; - if (!actor) - return; - - // build the new effect to be added - this.build_effect({ - unscaled_radius: 2 * this.settings.SIGMA, - brightness: this.settings.BRIGHTNESS, - }); - - // add the effect to the actor - if (this.actor) - this.actor.add_effect(this.effect); - else - this._warn(`could not add effect to actor, actor does not exist anymore`); - } - - build_effect(params) { - // create the effect - this.effect = this.effects_manager.new_native_dynamic_gaussian_blur_effect(params); - - // connect to settings changes, using the true gsettings object - this._sigma_changed_id = this.settings.settings.connect( - 'changed::sigma', () => this.effect.unscaled_radius = 2 * this.settings.SIGMA - ); - this._brightness_changed_id = this.settings.settings.connect( - 'changed::brightness', () => this.effect.brightness = this.settings.BRIGHTNESS - ); - } - - repaint_effect() { - this.effect?.queue_repaint(); - } - - /// Remove every effect from the actor it is attached to. Please note that they are not - /// destroyed, but rather stored (thanks to the `EffectManager` class) to be reused later. - remove_effect() { - this.effects_manager.remove(this.effect); - this.effect = null; - - if (this._sigma_changed_id) - this.settings.settings.disconnect(this._sigma_changed_id); - if (this._brightness_changed_id) - this.settings.settings.disconnect(this._brightness_changed_id); - delete this._sigma_changed_id; - delete this._brightness_changed_id; - } - - /// Do nothing for this dummy pipeline. - /// Note: exposed to public API. - change_pipeline_to() { return; } - - /// Note: exposed to public API. - destroy() { - this.remove_effect(); - this.actor = null; - } - - _warn(str) { - console.warn(`[Blur my Shell > dummy pip] ${str}`); - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js deleted file mode 100755 index 947d535f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/effects_manager.js +++ /dev/null @@ -1,90 +0,0 @@ -import { get_supported_effects } from '../effects/effects.js'; - -/// An object to manage effects (by not destroying them all the time) -export const EffectsManager = class EffectsManager { - constructor(connections) { - this.connections = connections; - this.used = []; - this.SUPPORTED_EFFECTS = get_supported_effects(); - - Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => { - // init the arrays containing each unused effect - this[effect_name + '_effects'] = []; - - // init the functions for each effect - this['new_' + effect_name + '_effect'] = function (params) { - let effect; - if (this[effect_name + '_effects'].length > 0) { - effect = this[effect_name + '_effects'].splice(0, 1)[0]; - effect.set({ - ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params - }); - } else - effect = new this.SUPPORTED_EFFECTS[effect_name].class({ - ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params - }); - - this.used.push(effect); - this.connect_to_destroy(effect); - return effect; - }; - }); - } - - connect_to_destroy(effect) { - effect.old_actor = effect.get_actor(); - if (effect.old_actor) - effect.old_actor_id = effect.old_actor.connect('destroy', _ => { - this.remove(effect, true); - }); - - this.connections.connect(effect, 'notify::actor', _ => { - let actor = effect.get_actor(); - - if (effect.old_actor && actor != effect.old_actor) - effect.old_actor.disconnect(effect.old_actor_id); - - if (actor && actor != effect.old_actor) { - effect.old_actor_id = actor.connect('destroy', _ => { - this.remove(effect, true); - }); - } - }); - } - - // IMPORTANT: do never call this in a mutable `this.used.forEach` - remove(effect, actor_already_destroyed = false) { - if (!actor_already_destroyed) - try { - effect.get_actor()?.remove_effect(effect); - } catch (e) { - this._warn(`could not remove the effect, continuing: ${e}`); - } - if (effect.old_actor) - effect.old_actor.disconnect(effect.old_actor_id); - delete effect.old_actor; - delete effect.old_actor_id; - - let index = this.used.indexOf(effect); - if (index >= 0) { - this.used.splice(index, 1); - - Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => { - if (effect instanceof this.SUPPORTED_EFFECTS[effect_name].class) - this[effect_name + '_effects'].push(effect); - }); - } - } - - destroy_all() { - const immutable_used_list = [...this.used]; - immutable_used_list.forEach(effect => this.remove(effect)); - Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => { - this[effect_name + '_effects'].splice(0, this[effect_name + '_effects'].length); - }); - } - - _warn(str) { - console.warn(`[Blur my Shell > effects mng] ${str}`); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/keys.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/keys.js deleted file mode 100755 index 9cf9b91b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/keys.js +++ /dev/null @@ -1,182 +0,0 @@ -import { Type } from './settings.js'; - -// This lists the preferences keys -export const KEYS = [ - { - component: "general", schemas: [ - { type: Type.PIPELINES, name: "pipelines" }, - { type: Type.I, name: "hacks-level" }, - { type: Type.B, name: "debug" }, - ] - }, - { - component: "overview", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.S, name: "pipeline" }, - { type: Type.I, name: "style-components" }, - ] - }, - { - component: "appfolder", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.I, name: "style-dialogs" }, - ] - }, - { - component: "panel", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.B, name: "static-blur" }, - { type: Type.S, name: "pipeline" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.B, name: "unblur-in-overview" }, - { type: Type.B, name: "force-light-text" }, - { type: Type.B, name: "override-background" }, - { type: Type.I, name: "style-panel" }, - { type: Type.B, name: "override-background-dynamically" }, - ] - }, - { - component: "dash-to-dock", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.B, name: "static-blur" }, - { type: Type.S, name: "pipeline" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.B, name: "unblur-in-overview" }, - { type: Type.B, name: "override-background" }, - { type: Type.I, name: "style-dash-to-dock" }, - ] - }, - { - component: "applications", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.I, name: "opacity" }, - { type: Type.B, name: "dynamic-opacity" }, - { type: Type.B, name: "blur-on-overview" }, - { type: Type.B, name: "enable-all" }, - { type: Type.AS, name: "whitelist" }, - { type: Type.AS, name: "blacklist" }, - ] - }, - { - component: "lockscreen", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.S, name: "pipeline" }, - ] - }, - { - component: "window-list", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.S, name: "pipeline" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - ] - }, - { - component: "screenshot", schemas: [ - { type: Type.B, name: "blur" }, - { type: Type.S, name: "pipeline" }, - ] - }, - { - component: "hidetopbar", schemas: [ - { type: Type.B, name: "compatibility" }, - ] - }, - { - component: "dash-to-panel", schemas: [ - { type: Type.B, name: "blur-original-panel" }, - ] - }, -]; - - -// This lists the deprecated preferences keys -export const DEPRECATED_KEYS = [ - { - component: "general", schemas: [ - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - { type: Type.B, name: "color-and-noise" }, - ] - }, - { - component: "overview", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, - { - component: "appfolder", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, - { - component: "panel", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, - { - component: "dash-to-dock", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - { type: Type.I, name: "corner-radius" }, - ] - }, - { - component: "applications", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, - { - component: "lockscreen", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, - { - component: "window-list", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, - { - component: "screenshot", schemas: [ - { type: Type.B, name: "customize" }, - { type: Type.I, name: "sigma" }, - { type: Type.D, name: "brightness" }, - { type: Type.C, name: "color" }, - { type: Type.D, name: "noise-amount" }, - { type: Type.D, name: "noise-lightness" }, - ] - }, -]; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/paint_signals.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/paint_signals.js deleted file mode 100755 index 5fbfee47..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/paint_signals.js +++ /dev/null @@ -1,91 +0,0 @@ -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; - - -export const PaintSignals = class PaintSignals { - constructor(connections) { - this.buffer = []; - this.connections = connections; - } - - connect(actor, blur_effect) { - let paint_effect = new EmitPaintSignal(); - let infos = { - actor: actor, - paint_effect: paint_effect - }; - let counter = 0; - - actor.add_effect(paint_effect); - this.connections.connect(paint_effect, 'update-blur', () => { - try { - // checking if blur_effect.queue_repaint() has been recently called - if (counter === 0) { - counter = 2; - blur_effect.queue_repaint(); - } - else counter--; - } catch (e) { } - }); - - // remove the actor from buffer when it is destroyed - if ( - actor.connect && - ( - !(actor instanceof GObject.Object) || - GObject.signal_lookup('destroy', actor) - ) - ) - this.connections.connect(actor, 'destroy', () => { - const immutable_buffer = [...this.buffer]; - immutable_buffer.forEach(infos => { - if (infos.actor === actor) { - // remove from buffer - let index = this.buffer.indexOf(infos); - this.buffer.splice(index, 1); - } - }); - }); - - this.buffer.push(infos); - } - - disconnect_all_for_actor(actor) { - const immutable_buffer = [...this.buffer]; - immutable_buffer.forEach(infos => { - if (infos.actor === actor) { - this.connections.disconnect_all_for(infos.paint_effect); - infos.actor.remove_effect(infos.paint_effect); - - // remove from buffer - let index = this.buffer.indexOf(infos); - this.buffer.splice(index, 1); - } - }); - } - - disconnect_all() { - this.buffer.forEach(infos => { - this.connections.disconnect_all_for(infos.paint_effect); - infos.actor.remove_effect(infos.paint_effect); - }); - - this.buffer = []; - } -}; - -export const EmitPaintSignal = GObject.registerClass({ - GTypeName: 'EmitPaintSignal', - Signals: { - 'update-blur': { - param_types: [] - }, - } -}, - class EmitPaintSignal extends Clutter.Effect { - vfunc_paint(node, paint_context, paint_flags) { - this.emit("update-blur"); - super.vfunc_paint(node, paint_context, paint_flags); - } - } -); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/pipeline.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/pipeline.js deleted file mode 100755 index f3099e75..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/pipeline.js +++ /dev/null @@ -1,204 +0,0 @@ -import St from 'gi://St'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Background from 'resource:///org/gnome/shell/ui/background.js'; - -/// A `Pipeline` object is a handy way to manage the effects attached to an actor. It only manages -/// one actor at a time (so blurring multiple widgets will need multiple `Pipeline`), and is -/// linked to a `pipeline_id` that has been (hopefully) defined in the settings. -/// -/// It communicates with the settings through the `PipelinesManager` object, and receives different -/// signals (with `pipeline_id` being an unique string): -/// - `'pipeline_id'::pipeline-updated`, handing a new pipeline descriptor object, when the pipeline -/// has been changed enough that it needs to rebuild the effects configuration -/// - `'pipeline_id'::pipeline-destroyed`, when the pipeline has been destroyed; thus making the -/// `Pipeline` change its id to `pipeline_default` -/// -/// And each effect, with an unique `id`, is connected to the `PipelinesManager` for the signals: -/// - `'pipeline_id'::effect-'id'-key-removed`, handing the key that was removed -/// - `'pipeline_id'::effect-'id'-key-updated`, handing the key that was changed and its new value -/// - `'pipeline_id'::effect-'id'-key-added`, handing the key that was added and its value -export const Pipeline = class Pipeline { - constructor(effects_manager, pipelines_manager, pipeline_id, actor = null) { - this.effects_manager = effects_manager; - this.pipelines_manager = pipelines_manager; - this.effects = []; - this.set_pipeline_id(pipeline_id); - this.attach_pipeline_to_actor(actor); - } - - /// Create a background linked to the monitor with index `monitor_index`, with a - /// `BackgroundManager` that is appended to the list `background_managers`. The background actor - /// will be given the name `widget_name` and inserted into the given `background_group`. - /// Note: exposed to public API. - create_background_with_effects( - monitor_index, - background_managers, - background_group, - widget_name - ) { - let monitor = Main.layoutManager.monitors[monitor_index]; - - // create the new actor - this.actor = new St.Widget({ - name: widget_name, - x: monitor.x, - y: monitor.y, - width: monitor.width, - height: monitor.height - }); - - // remove the effects, wether or not we attach the pipeline to the actor: if they are fired - // while the actor has changed, this could go bad - this.remove_all_effects(); - if (this.pipeline_id) - this.attach_pipeline_to_actor(this.actor); - - let bg_manager = new Background.BackgroundManager({ - container: this.actor, - monitorIndex: monitor_index, - controlPosition: false, - }); - bg_manager._bms_pipeline = this; - - background_managers.push(bg_manager); - background_group.insert_child_at_index(this.actor, 0); - - return this.actor; - }; - - /// Set the pipeline id, correctly connecting the `Pipeline` object to listen the pipelines - /// manager for pipeline-wide changes. This does not update the effects in consequence, call - /// `change_pipeline_to` instead if you want to reconstruct the effects too. - set_pipeline_id(pipeline_id) { - // disconnect ancient signals - this.remove_connections(); - - // change the id - this.pipeline_id = pipeline_id; - - // connect to settings changes - this._pipeline_changed_id = this.pipelines_manager.connect( - this.pipeline_id + '::pipeline-updated', - (_, new_pipeline) => this.update_effects_from_pipeline(new_pipeline) - ); - this._pipeline_destroyed_id = this.pipelines_manager.connect( - this.pipeline_id + '::pipeline-destroyed', - _ => this.change_pipeline_to("pipeline_default") - ); - } - - /// Disconnect the signals for the pipeline changes. Please note that the signals related to the - /// effects are stored with them and removed with `remove_all_effects`. - remove_connections() { - if (this._pipeline_changed_id) - this.pipelines_manager.disconnect(this._pipeline_changed_id); - if (this._pipeline_destroyed_id) - this.pipelines_manager.disconnect(this._pipeline_destroyed_id); - this._pipeline_changed_id = null; - this._pipeline_destroyed_id = null; - } - - /// Attach a Pipeline object with `pipeline_id` already set to an actor. - attach_pipeline_to_actor(actor) { - // set the actor - this.actor = actor; - if (!actor) - return; - - // attach the pipeline - let pipeline = this.pipelines_manager.pipelines[this.pipeline_id]; - if (!pipeline) { - this._warn(`could not attach pipeline to actor, pipeline "${this.pipeline_id}" not found`); - // do not recurse... - if ("pipeline_default" in this.pipelines_manager.pipelines) { - this.set_pipeline_id("pipeline_default"); - pipeline = this.pipelines_manager.pipelines["pipeline_default"]; - } else - return; - } - - // update the effects - this.update_effects_from_pipeline(pipeline); - } - - /// Update the effects from the given pipeline object, the hard way. - update_effects_from_pipeline(pipeline) { - // remove all effects - this.remove_all_effects(); - - // build the new effects to be added - pipeline.effects.forEach(effect => { - if ('new_' + effect.type + '_effect' in this.effects_manager) - this.build_effect(effect); - else - this._warn(`could not add effect to actor, effect "${effect.type}" not found`); - }); - this.effects.reverse(); - - // add the effects to the actor - if (this.actor) - this.effects.forEach(effect => this.actor.add_effect(effect)); - else - this._warn(`could not add effect to actor, actor does not exist anymore`); - } - - /// Given an `effect_infos` object containing the effect type, id and params, build an effect - /// and append it to the effects list - build_effect(effect_infos) { - let effect = this.effects_manager['new_' + effect_infos.type + '_effect'](effect_infos.params); - this.effects.push(effect); - - // connect to settings changes - effect._effect_key_removed_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-removed', - (_, key) => effect[key] = effect.constructor.default_params[key] - ); - effect._effect_key_updated_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-updated', - (_, key, value) => effect[key] = value - ); - effect._effect_key_added_id = this.pipelines_manager.connect( - this.pipeline_id + '::effect-' + effect_infos.id + '-key-added', - (_, key, value) => effect[key] = value - ); - } - - /// Remove every effect from the actor it is attached to. Please note that they are not - /// destroyed, but rather stored (thanks to the `EffectManager` class) to be reused later. - remove_all_effects() { - this.effects.forEach(effect => { - this.effects_manager.remove(effect); - [ - effect._effect_key_removed_id, - effect._effect_key_updated_id, - effect._effect_key_added_id - ].forEach( - id => { if (id) this.pipelines_manager.disconnect(id); } - ); - delete effect._effect_key_removed_id; - delete effect._effect_key_updated_id; - delete effect._effect_key_added_id; - }); - this.effects = []; - } - - /// Change the pipeline id, and update the effects according to this change. - /// Note: exposed to public API. - change_pipeline_to(pipeline_id) { - this.set_pipeline_id(pipeline_id); - this.attach_pipeline_to_actor(this.actor); - } - - /// Resets the `Pipeline` object to a sane state, removing every effect and signal. - /// Note: exposed to public API. - destroy() { - this.remove_all_effects(); - this.remove_connections(); - this.actor = null; - this.pipeline_id = null; - } - - _warn(str) { - console.warn(`[Blur my Shell > pipeline] ${str}`); - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/pipelines_manager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/pipelines_manager.js deleted file mode 100755 index 0fdfe9ea..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/pipelines_manager.js +++ /dev/null @@ -1,168 +0,0 @@ -const Signals = imports.signals; - -/// The `PipelinesManager` object permits to store the list of pipelines and their effects in -/// memory. It is meant to *always* be in sync with the `org.gnome.shell.extensions.blur-my-shell`'s -/// `pipelines` gschema. However, we do not want to re-create every effect each time this schema is -/// changed, so the pipelines manager handles it, and dispatches the updates with targeted signals. -/// -/// It is only connected to ONE signal (the pipelines schema being changed), and emits numerous -/// which are connected to by both the different `Pipeline` objects in the extension, and by the -/// different pages of the extension preferences. -/// It emits three different types of signals: -/// -/// - general changes to the pipelines list, connected to by the extension preferences: -/// - `pipeline-list-changed`, when the list of pipelines has changed (by creation or deletion) -/// - `pipeline-names-changed`, when the name of a pipeline is changed -/// -/// - signals that are targeted towards a given pipeline, with `pipeline_id` being its unique id: -/// - `'pipeline_id'::pipeline-updated`, handing a new pipeline descriptor object, when the -/// pipeline has been changed quite a bit (added/destroyed/reordered the effects) -/// - `'pipeline_id'::pipeline-destroyed`, when the pipeline has been destroyed -/// - `'pipeline_id'::pipeline-renamed`, handing the new name, when the pipeline has been -/// renamed, which is only important for the preferences -/// -/// - signals that are targeted towards a given effect, with `effect_id` being its unique id, and -/// `pipeline_id` the unique id of the pipeline it is attached to: -/// - `'pipeline_id'::effect-'effect_id'-key-removed`, handing the key that was removed -/// - `'pipeline_id'::effect-'effect_id'-key-updated`, handing the key that was changed and its -/// new value -/// - `'pipeline_id'::effect-'effect_id'-key-added`, handing the key that was added and its -/// value -export class PipelinesManager { - constructor(settings) { - this.settings = settings; - this.pipelines = this.settings.PIPELINES; - this.settings.PIPELINES_changed(_ => this.on_pipeline_update()); - } - - create_pipeline(name, effects = []) { - // select a random id for the pipeline - let id = "pipeline_" + ("" + Math.random()).slice(2, 16); - // add a random ID for each effect, to help tracking them - effects.forEach(effect => effect.id = "effect_" + ("" + Math.random()).slice(2, 16)); - - this.pipelines[id] = { name, effects }; - this.settings.PIPELINES = this.pipelines; - this._emit('pipeline-created', id, this.pipelines[id]); - this._emit('pipeline-list-changed'); - return id; - } - - duplicate_pipeline(id) { - if (!(id in this.pipelines)) { - this._warn(`could not duplicate pipeline, id ${id} does not exist`); - return; - } - const pipeline = this.pipelines[id]; - this.create_pipeline(pipeline.name + " - duplicate", [...pipeline.effects]); - this.settings.PIPELINES = this.pipelines; - } - - delete_pipeline(id) { - if (!(id in this.pipelines)) { - this._warn(`could not delete pipeline, id ${id} does not exist`); - return; - } - if (id == "pipeline_default") { - this._warn(`could not delete pipeline "pipeline_default" as it is immutable`); - return; - } - delete this.pipelines[id]; - this.settings.PIPELINES = this.pipelines; - this._emit(id + '::pipeline-destroyed'); - this._emit('pipeline-list-changed'); - } - - update_pipeline_effects(id, effects, emit_update_signal = true) { - if (!(id in this.pipelines)) { - this._warn(`could not update pipeline effects, id ${id} does not exist`); - return; - } - this.pipelines[id].effects = [...effects]; - this.settings.PIPELINES = this.pipelines; - if (emit_update_signal) - this._emit(id + '::pipeline-updated'); - } - - rename_pipeline(id, name) { - if (!(id in this.pipelines)) { - this._warn(`could not rename pipeline, id ${id} does not exist`); - return; - } - this.pipelines[id].name = name.slice(); - this.settings.PIPELINES = this.pipelines; - this._emit(id + '::pipeline-renamed', name); - this._emit('pipeline-names-changed'); - } - - on_pipeline_update() { - const old_pipelines = this.pipelines; - this.pipelines = this.settings.PIPELINES; - - for (var pipeline_id in old_pipelines) { - // if we find a pipeline that does not exist anymore, signal it - if (!(pipeline_id in this.pipelines)) { - this._emit(pipeline_id + '::pipeline-destroyed'); - continue; - } - - const old_pipeline = old_pipelines[pipeline_id]; - const new_pipeline = this.pipelines[pipeline_id]; - - // verify if both pipelines have effects in the same order - // if they have, then check for their parameters - if ( - old_pipeline.effects.length == new_pipeline.effects.length && - old_pipeline.effects.every((effect, i) => effect.id === new_pipeline.effects[i].id) - ) { - for (let i = 0; i < old_pipeline.effects.length; i++) { - const old_effect = old_pipeline.effects[i]; - const new_effect = new_pipeline.effects[i]; - const id = old_effect.id; - for (let key in old_effect.params) { - // if a key was removed, we emit to tell the effect to use the default value - if (!(key in new_effect.params)) - this._emit( - pipeline_id + '::effect-' + id + '-key-removed', key - ); - // if a key was updated, we emit to tell the effect to change its value - else if (old_effect.params[key] != new_effect.params[key]) - this._emit( - pipeline_id + '::effect-' + id + '-key-updated', key, new_effect.params[key] - ); - } - for (let key in new_effect.params) { - // if a key was added, we emit to tell the effect the key and its value - if (!(key in old_effect.params)) - this._emit( - pipeline_id + '::effect-' + id + '-key-added', key, new_effect.params[key] - ); - } - } - } - // if either the order has changed, or there are new effects, then rebuild it - else - this._emit(pipeline_id + '::pipeline-updated', new_pipeline); - } - } - - destroy() { - this.settings.PIPELINES_disconnect(); - } - - _emit(signal, ...args) { - this.emit(signal, ...args); - this._log(`signal: '${signal}', arguments: ${args}`); - } - - _log(str) { - if (this.settings.DEBUG) - console.log(`[Blur my Shell > pipelines] ${str}`); - } - - _warn(str) { - console.warn(`[Blur my Shell > pipelines] ${str}`); - } -} - -Signals.addSignalMethods(PipelinesManager.prototype); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/settings.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/settings.js deleted file mode 100755 index 53f8497c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/settings.js +++ /dev/null @@ -1,363 +0,0 @@ -import GLib from 'gi://GLib'; -const Signals = imports.signals; - -/// An enum non-extensively describing the type of gsettings key. -export const Type = { - B: 'Boolean', - I: 'Integer', - D: 'Double', - S: 'String', - C: 'Color', - AS: 'StringArray', - PIPELINES: 'Pipelines' -}; - -/// An object to get and manage the gsettings preferences. -/// -/// Should be initialized with an array of keys, for example: -/// -/// let settings = new Settings([ -/// { type: Type.I, name: "panel-corner-radius" }, -/// { type: Type.B, name: "debug" } -/// ]); -/// -/// Each {type, name} object represents a gsettings key, which must be created -/// in the gschemas.xml file of the extension. -export const Settings = class Settings { - constructor(keys, settings) { - this.settings = settings; - this.keys = keys; - - this.keys.forEach(bundle => { - let component = this; - let component_settings = settings; - if (bundle.component !== "general") { - let bundle_component = bundle.component.replaceAll('-', '_'); - this[bundle_component] = { - settings: this.settings.get_child(bundle.component) - }; - component = this[bundle_component]; - component_settings = settings.get_child(bundle.component); - } - - - bundle.schemas.forEach(key => { - let property_name = this.get_property_name(key.name); - - switch (key.type) { - case Type.B: - Object.defineProperty(component, property_name, { - get() { - return component_settings.get_boolean(key.name); - }, - set(v) { - component_settings.set_boolean(key.name, v); - } - }); - break; - - case Type.I: - Object.defineProperty(component, property_name, { - get() { - return component_settings.get_int(key.name); - }, - set(v) { - component_settings.set_int(key.name, v); - } - }); - break; - - case Type.D: - Object.defineProperty(component, property_name, { - get() { - return component_settings.get_double(key.name); - }, - set(v) { - component_settings.set_double(key.name, v); - } - }); - break; - - case Type.S: - Object.defineProperty(component, property_name, { - get() { - return component_settings.get_string(key.name); - }, - set(v) { - component_settings.set_string(key.name, v); - } - }); - break; - - case Type.C: - Object.defineProperty(component, property_name, { - // returns the array [red, blue, green, alpha] with - // values between 0 and 1 - get() { - let val = component_settings.get_value(key.name); - return val.deep_unpack(); - }, - // takes an array [red, blue, green, alpha] with - // values between 0 and 1 - set(v) { - let val = new GLib.Variant("(dddd)", v); - component_settings.set_value(key.name, val); - } - }); - break; - - case Type.AS: - Object.defineProperty(component, property_name, { - get() { - let val = component_settings.get_value(key.name); - return val.deep_unpack(); - }, - set(v) { - let val = new GLib.Variant("as", v); - component_settings.set_value(key.name, val); - } - }); - break; - - case Type.PIPELINES: - Object.defineProperty(component, property_name, { - get() { - let pips = component_settings.get_value(key.name).deep_unpack(); - Object.keys(pips).forEach(pipeline_id => { - let pipeline = pips[pipeline_id]; - - if (!('name' in pipeline)) { - this._warn('impossible to get pipelines, pipeline has not name, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - let name = pipeline.name.deep_unpack(); - if (typeof name !== 'string') { - this._warn('impossible to get pipelines, pipeline name is not a string, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - - if (!('effects' in pipeline)) { - this._warn('impossible to get pipelines, pipeline has not effects, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - let effects = pipeline.effects.deep_unpack(); - if (!Array.isArray(effects)) { - this._warn('impossible to get pipelines, pipeline effects is not an array, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - - effects = effects.map(effect => effect.deep_unpack()); - effects.forEach(effect => { - if (!('type' in effect)) { - this._warn('impossible to get pipelines, effect has not type, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - let type = effect.type.deep_unpack(); - if (typeof type !== 'string') { - this._warn('impossible to get pipelines, effect type is not a string, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - - if (!('id' in effect)) { - this._warn('impossible to get pipelines, effect has not id, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - let id = effect.id.deep_unpack(); - if (typeof id !== 'string') { - this._warn('impossible to get pipelines, effect id is not a string, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - - let params = {}; - if ('params' in effect) - params = effect.params.deep_unpack(); - if (!(params && typeof params === 'object' && params.constructor === Object)) { - this._warn('impossible to get pipelines, effect params is not an object, resetting'); - component[property_name + '_reset'](); - return component[property_name]; - } - Object.keys(params).forEach(param_key => { - params[param_key] = params[param_key].deep_unpack(); - }); - - effect.type = type; - effect.id = id; - effect.params = params; - }); - pipeline.name = name; - pipeline.effects = effects; - }); - return pips; - }, - set(pips) { - let pipelines = {}; - Object.keys(pips).forEach(pipeline_id => { - let pipeline = pips[pipeline_id]; - if (!(pipeline && typeof pipeline === 'object' && pipeline.constructor === Object)) { - this._warn('impossible to set pipelines, pipeline is not an object'); - return; - } - - if (!('name' in pipeline)) { - this._warn('impossible to set pipelines, pipeline has no name'); - return; - } - if (typeof pipeline.name !== 'string') { - this._warn('impossible to set pipelines, pipeline name is not a string'); - return; - } - - if (!('effects' in pipeline)) { - this._warn('impossible to set pipelines, pipeline has no effect'); - return; - } - if (!Array.isArray(pipeline.effects)) { - this._warn('impossible to set pipelines, effects is not an array'); - return; - } - - let gvariant_effects = []; - pipeline.effects.forEach(effect => { - if (!(effect instanceof Object)) { - this._warn('impossible to set pipelines, effect is not an object'); - return; - } - - if (!('type' in effect)) { - this._warn('impossible to set pipelines, effect has not type'); - return; - } - if (typeof effect.type !== 'string') { - this._warn('impossible to set pipelines, effect type is not a string'); - return; - } - - if (!('id' in effect)) { - this._warn('impossible to set pipelines, effect has not id'); - return; - } - if (typeof effect.id !== 'string') { - this._warn('impossible to set pipelines, effect id is not a string'); - return; - } - - let params = {}; - if ('params' in effect) { - params = effect.params; - } - let gvariant_params = {}; - Object.keys(params).forEach(param_key => { - let param = params[param_key]; - if (typeof param === 'boolean') - gvariant_params[param_key] = GLib.Variant.new_boolean(param); - else if (typeof param === 'number') { - if (Number.isInteger(param)) - gvariant_params[param_key] = GLib.Variant.new_int32(param); - else - gvariant_params[param_key] = GLib.Variant.new_double(param); - } else if (typeof param === 'string') - gvariant_params[param_key] = GLib.Variant.new_string(param); - else if (Array.isArray(param) && param.length == 4) - gvariant_params[param_key] = new GLib.Variant("(dddd)", param); - else - this._warn('impossible to set pipeline, effect parameter type is unknown'); - }); - - gvariant_effects.push( - new GLib.Variant("a{sv}", { - type: GLib.Variant.new_string(effect.type), - id: GLib.Variant.new_string(effect.id), - params: new GLib.Variant("a{sv}", gvariant_params) - }) - ); - }); - - pipelines[pipeline_id] = { - name: GLib.Variant.new_string(pipeline.name), - effects: new GLib.Variant("av", gvariant_effects) - }; - }); - let val = new GLib.Variant("a{sa{sv}}", pipelines); - component_settings.set_value(key.name, val); - } - }); - break; - } - - - component[property_name + '_reset'] = function () { - return component_settings.reset(key.name); - }; - - component[property_name + '_signal_ids'] = []; - component[property_name + '_changed'] = function (cb) { - component[property_name + '_signal_ids'].push( - component_settings.connect('changed::' + key.name, cb) - ); - }; - - component[property_name + '_disconnect'] = function () { - component[property_name + '_signal_ids'].forEach( - id => component_settings.disconnect(id) - ); - component[property_name + '_signal_ids'] = []; - }; - }); - }); - }; - - /// Reset the preferences. - reset() { - this.keys.forEach(bundle => { - let component = this; - if (bundle.component !== "general") { - let bundle_component = bundle.component.replaceAll('-', '_'); - component = this[bundle_component]; - } - - bundle.schemas.forEach(key => { - let property_name = this.get_property_name(key.name); - component[property_name + '_reset'](); - }); - }); - - this.emit('reset', true); - } - - /// From the gschema name, returns the name of the associated property on - /// the Settings object. - get_property_name(name) { - return name.replaceAll('-', '_').toUpperCase(); - } - - /// Remove all connections managed by the Settings object, i.e. created with - /// `settings.PROPERTY_changed(callback)`. - disconnect_all_settings() { - this.keys.forEach(bundle => { - let component = this; - if (bundle.component !== "general") { - let bundle_component = bundle.component.replaceAll('-', '_'); - component = this[bundle_component]; - } - - bundle.schemas.forEach(key => { - let property_name = this.get_property_name(key.name); - component[property_name + '_disconnect'](); - }); - }); - } - - _warn(str) { - console.warn(`[Blur my Shell > settings] ${str}`); - } -}; - -Signals.addSignalMethods(Settings.prototype); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/settings_updater.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/settings_updater.js deleted file mode 100755 index 2affbc1a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/settings_updater.js +++ /dev/null @@ -1,40 +0,0 @@ -import { Settings } from './settings.js'; -import { KEYS, DEPRECATED_KEYS } from './keys.js'; - -const CURRENT_SETTINGS_VERSION = 2; - -export function update_from_old_settings(gsettings) { - const preferences = new Settings(KEYS, gsettings); - const deprecated_preferences = new Settings(DEPRECATED_KEYS, gsettings); - const old_version = preferences.settings.get_int('settings-version'); - - if (old_version < CURRENT_SETTINGS_VERSION) { - // set artifacts hacks to be 1 at most, as it should be suitable now that most big bugs have - // been resolved (and especially because hack levels to 2 now means disabling clipped - // redraws entirely, which is very much not what we want for users that update) - if (preferences.HACKS_LEVEL > 1) - preferences.HACKS_LEVEL = 1; - - // enable dash-to-dock blurring, as most disabled it due to the lack of rounded corners; set - // it to static blur by default too and with transparent background - preferences.dash_to_dock.BLUR = true; - preferences.dash_to_dock.STATIC_BLUR = true; - preferences.dash_to_dock.STYLE_DASH_TO_DOCK = 0; - - // 'customize' has been removed: we merge the current used settings - ['appfolder', 'panel', 'dash_to_dock', 'applications', 'window_list'].forEach( - component_name => { - const deprecated_component = deprecated_preferences[component_name]; - const new_component = preferences[component_name]; - if (!deprecated_component.CUSTOMIZE) { - new_component.SIGMA = deprecated_preferences.SIGMA; - new_component.BRIGHTNESS = deprecated_preferences.BRIGHTNESS; - } - }); - - // remove old preferences in order not to clutter the gsettings - deprecated_preferences.reset(); - } - - preferences.settings.set_int('settings-version', CURRENT_SETTINGS_VERSION); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/utils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/utils.js deleted file mode 100755 index 7a2c3908..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/conveniences/utils.js +++ /dev/null @@ -1,27 +0,0 @@ -import GLib from 'gi://GLib'; - -export const IS_IN_PREFERENCES = typeof global === 'undefined'; - -// Taken from https://github.com/Schneegans/Burn-My-Windows/blob/main/src/utils.js -// This method can be used to import a module in the GNOME Shell process only. This -// is useful if you want to use a module in extension.js, but not in the preferences -// process. This method returns null if it is called in the preferences process. -export async function import_in_shell_only(module) { - if (IS_IN_PREFERENCES) - return null; - return (await import(module)).default; -} - -export const get_shader_source = (Shell, shader_filename, self_uri) => { - if (!Shell) - return; - const shader_path = GLib.filename_from_uri( - GLib.uri_resolve_relative(self_uri, shader_filename, GLib.UriFlags.NONE) - )[0]; - try { - return Shell.get_file_contents_utf8_sync(shader_path); - } catch (e) { - console.warn(`[Blur my Shell > effect] error loading shader from ${shader_path}: ${e}`); - return null; - } -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/client.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/client.js deleted file mode 100755 index 3867b3a6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/client.js +++ /dev/null @@ -1,58 +0,0 @@ -import Gio from 'gi://Gio'; - -const bus_name = 'org.gnome.Shell'; -const iface_name = 'dev.aunetx.BlurMyShell'; -const obj_path = '/dev/aunetx/BlurMyShell'; - - -/// Call pick() from the DBus service, it will open the Inspector from -/// gnome-shell to pick an actor on stage. -export function pick() { - Gio.DBus.session.call( - bus_name, - obj_path, - iface_name, - 'pick', - null, - null, - Gio.DBusCallFlags.NO_AUTO_START, - -1, - null, - null - ); -} - -/// Connect to DBus 'picking' signal, which will be emitted when the inspector -/// is picking a window. -export function on_picking(cb) { - const id = Gio.DBus.session.signal_subscribe( - bus_name, - iface_name, - 'picking', - obj_path, - null, - Gio.DBusSignalFlags.NONE, - _ => { - cb(); - Gio.DBus.session.signal_unsubscribe(id); - } - ); -} - -/// Connect to DBus 'picked' signal, which will be emitted when a window is -/// picked. -export function on_picked(cb) { - const id = Gio.DBus.session.signal_subscribe( - bus_name, - iface_name, - 'picked', - obj_path, - null, - Gio.DBusSignalFlags.NONE, - (conn, sender, obj_path, iface, signal, params) => { - const val = params.get_child_value(0); - cb(val.get_string()[0]); - Gio.DBus.session.signal_unsubscribe(id); - } - ); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/iface.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/iface.xml deleted file mode 100755 index 4f298ad1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/iface.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/services.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/services.js deleted file mode 100755 index 4b1f4f0c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/dbus/services.js +++ /dev/null @@ -1,93 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'; - - -export const ApplicationsService = class ApplicationsService { - constructor() { - let decoder = new TextDecoder(); - let path = GLib.filename_from_uri(GLib.uri_resolve_relative( - import.meta.url, 'iface.xml', GLib.UriFlags.NONE) - )[0]; - let [, buffer] = GLib.file_get_contents(path); - let iface = decoder.decode(buffer); - GLib.free(buffer); - - this.DBusImpl = Gio.DBusExportedObject.wrapJSObject(iface, this); - } - - /// Pick Window for Preferences Page, exported to DBus client. - pick() { - // emit `picking` signal to know we are listening - const send_picking_signal = _ => - this.DBusImpl.emit_signal( - 'picking', - null - ); - - // emit `picked` signal to send wm_class - const send_picked_signal = wm_class => - this.DBusImpl.emit_signal( - 'picked', - new GLib.Variant('(s)', [wm_class]) - ); - - // notify the preferences that we are listening - send_picking_signal(); - - // A very interesting way to pick a window: - // 1. Open LookingGlass to mask all event handles of window - // 2. Use inspector to pick window, thats is also lookingGlass do - // 3. Close LookingGlass when done - // It will restore event handles of window - - // open then hide LookingGlass - const looking_class = Main.createLookingGlass(); - looking_class.open(); - looking_class.hide(); - - // inspect window now - const inspector = new LookingGlass.Inspector(Main.createLookingGlass()); - inspector.connect('target', (me, target, x, y) => { - // remove border effect when window is picked. - const effect_name = 'lookingGlass_RedBorderEffect'; - target - .get_effects() - .filter(e => e.toString().includes(effect_name)) - .forEach(e => target.remove_effect(e)); - - // get wm_class_instance property of window, then pass it to DBus - // client - const type_str = target.toString(); - - let actor = target; - if (type_str.includes('MetaSurfaceActor')) - actor = target.get_parent(); - - if (!actor.toString().includes('WindowActor')) - actor = actor.get_parent(); - - if (!actor.toString().includes('WindowActor')) - return send_picked_signal('window-not-found'); - - send_picked_signal( - actor.meta_window.get_wm_class() ?? 'window-not-found' - ); - }); - - // close LookingGlass when we're done - inspector.connect('closed', _ => looking_class.close()); - } - - export() { - this.DBusImpl.export( - Gio.DBus.session, - '/dev/aunetx/BlurMyShell' - ); - }; - - unexport() { - this.DBusImpl.unexport(); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/color.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/color.glsl deleted file mode 100755 index 142b89bf..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/color.glsl +++ /dev/null @@ -1,13 +0,0 @@ -uniform sampler2D tex; -uniform float red; -uniform float green; -uniform float blue; -uniform float blend; - -void main() { - vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); - vec3 pix_color = c.xyz; - vec3 color = vec3(red, green, blue); - - cogl_color_out = vec4(mix(pix_color, color, blend), 1.); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/color.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/color.js deleted file mode 100755 index 9729400f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/color.js +++ /dev/null @@ -1,151 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const Shell = await utils.import_in_shell_only('gi://Shell'); -const Clutter = await utils.import_in_shell_only('gi://Clutter'); - -const SHADER_FILENAME = 'color.glsl'; -const DEFAULT_PARAMS = { - color: [0.0, 0.0, 0.0, 0.0] -}; - - -export const ColorEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "ColorEffect", - Properties: { - 'red': GObject.ParamSpec.double( - `red`, - `Red`, - `Red value in shader`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.0, - ), - 'green': GObject.ParamSpec.double( - `green`, - `Green`, - `Green value in shader`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.0, - ), - 'blue': GObject.ParamSpec.double( - `blue`, - `Blue`, - `Blue value in shader`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.0, - ), - 'blend': GObject.ParamSpec.double( - `blend`, - `Blend`, - `Amount of blending between the colors`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.0, - ), - } - }, class ColorEffect extends Clutter.ShaderEffect { - constructor(params) { - // initialize without color as a parameter - const { color, ...parent_params } = params; - super(parent_params); - - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); - - // set shader color - this.color = 'color' in params ? color : this.constructor.default_params.color; - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get red() { - return this._red; - } - - set red(value) { - if (this._red !== value) { - this._red = value; - - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); - } - } - - get green() { - return this._green; - } - - set green(value) { - if (this._green !== value) { - this._green = value; - - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); - } - } - - get blue() { - return this._blue; - } - - set blue(value) { - if (this._blue !== value) { - this._blue = value; - - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); - } - } - - get blend() { - return this._blend; - } - - set blend(value) { - if (this._blend !== value) { - this._blend = value; - - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); - this.set_enabled(this.blend > 0); - } - } - - set color(rgba) { - let [r, g, b, a] = rgba; - this.red = r; - this.green = g; - this.blue = b; - this.blend = a; - } - - get color() { - return [this.red, this.green, this.blue, this.blend]; - } - - /// False set function, only cares about the color. Too hard to change. - set(params) { - this.color = params.color; - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/corner.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/corner.glsl deleted file mode 100755 index 760798ae..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/corner.glsl +++ /dev/null @@ -1,93 +0,0 @@ -// Heavily based on https://github.com/yilozt/rounded-window-corners -// which is itself based on upstream Mutter code - -uniform sampler2D tex; -uniform float radius; -uniform float width; -uniform float height; -uniform bool corners_top; -uniform bool corners_bottom; - -uniform float clip_x0; -uniform float clip_y0; -uniform float clip_width; -uniform float clip_height; - -float circle_bounds(vec2 p, vec2 center, float clip_radius) { - vec2 delta = p - center; - float dist_squared = dot(delta, delta); - - float outer_radius = clip_radius + 0.5; - if (dist_squared >= (outer_radius * outer_radius)) - return 0.0; - - float inner_radius = clip_radius - 0.5; - if (dist_squared <= (inner_radius * inner_radius)) - return 1.0; - - return outer_radius - sqrt(dist_squared); -} - -vec4 getTexture(vec2 uv) { - if (uv.x < 2. / width) - uv.x = 2. / width; - - if (uv.y < 2. / height) - uv.y = 2. / height; - - if (uv.x > 1. - 3. / width) - uv.x = 1. - 3. / width; - - if (uv.y > 1. - 3. / height) - uv.y = 1. - 3. / height; - - return texture2D(tex, uv); -} - -float rounded_rect_coverage(vec2 p, vec4 bounds, float clip_radius) { - // Outside the bounds - if (p.x < bounds.x || p.x > bounds.z || p.y < bounds.y || p.y > bounds.w) { - return 0.; - } - - vec2 center; - - float center_left = bounds.x + clip_radius; - float center_right = bounds.z - clip_radius; - - if (p.x < center_left) - center.x = center_left + 2.; - else if (p.x > center_right) - center.x = center_right - 1.; - else - return 1.0; - - float center_top = bounds.y + clip_radius; - float center_bottom = bounds.w - clip_radius; - - if (corners_top && p.y < center_top) - center.y = center_top + 2.; - else if (corners_bottom && p.y > center_bottom) - center.y = center_bottom - 1.; - else - return 1.0; - - return circle_bounds(p, center, clip_radius); -} - -void main(void) { - vec2 uv = cogl_tex_coord_in[0].xy; - vec2 pos = uv * vec2(width, height); - vec4 c = getTexture(uv); - - vec4 bounds; - if (clip_width < 0. || clip_height < 0.) { - bounds = vec4(clip_x0, clip_y0, clip_x0 + width, clip_y0 + height); - } else { - bounds = vec4(clip_x0, clip_y0, clip_x0 + clip_width, clip_y0 + clip_height); - } - - float alpha = rounded_rect_coverage(pos, bounds, radius); - - cogl_color_out = vec4(c.rgb * alpha, min(alpha, c.a)); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/corner.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/corner.js deleted file mode 100755 index 1a9d21cb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/corner.js +++ /dev/null @@ -1,233 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const St = await utils.import_in_shell_only('gi://St'); -const Shell = await utils.import_in_shell_only('gi://Shell'); -const Clutter = await utils.import_in_shell_only('gi://Clutter'); - -const SHADER_FILENAME = 'corner.glsl'; -const DEFAULT_PARAMS = { - radius: 12, width: 0, height: 0, - corners_top: true, corners_bottom: true, - clip: [0, 0, -1, -1] -}; - - -export const CornerEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "CornerEffect", - Properties: { - 'radius': GObject.ParamSpec.double( - `radius`, - `Corner Radius`, - `Corner Radius`, - GObject.ParamFlags.READWRITE, - 0, Number.MAX_SAFE_INTEGER, - 12, - ), - 'width': GObject.ParamSpec.double( - `width`, - `Width`, - `Width`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'height': GObject.ParamSpec.double( - `height`, - `Height`, - `Height`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'corners_top': GObject.ParamSpec.boolean( - `corners_top`, - `Round top corners`, - `Round top corners`, - GObject.ParamFlags.READWRITE, - true, - ), - 'corners_bottom': GObject.ParamSpec.boolean( - `corners_bottom`, - `Round bottom corners`, - `Round bottom corners`, - GObject.ParamFlags.READWRITE, - true, - ), - // FIXME this works but it logs an error, because I'm not a double... - // I don't want to fiddle with GVariants again - 'clip': GObject.ParamSpec.double( - `clip`, - `Clip`, - `Clip`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - } - }, class CornerEffect extends Clutter.ShaderEffect { - constructor(params) { - super(params); - - this._radius = null; - this._width = null; - this._height = null; - this._corners_top = null; - this._corners_bottom = null; - - this._clip_x0 = null; - this._clip_y0 = null; - this._clip_width = null; - this._clip_height = null; - - this.radius = 'radius' in params ? params.radius : this.constructor.default_params.radius; - this.width = 'width' in params ? params.width : this.constructor.default_params.width; - this.height = 'height' in params ? params.height : this.constructor.default_params.height; - this.height = 'corners_top' in params ? params.corners_top : this.constructor.default_params.corners_top; - this.height = 'corners_bottom' in params ? params.corners_bottom : this.constructor.default_params.corners_bottom; - this.clip = 'clip' in params ? params.clip : this.constructor.default_params.clip; - - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); - - const theme_context = St.ThemeContext.get_for_stage(global.stage); - theme_context.connectObject('notify::scale-factor', _ => this.update_radius(), this); - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get radius() { - return this._radius; - } - - set radius(value) { - if (this._radius !== value) { - this._radius = value; - - this.update_radius(); - } - } - - update_radius() { - const theme_context = St.ThemeContext.get_for_stage(global.stage); - let radius = Math.min( - this.radius * theme_context.scale_factor, - this.width / 2, this.height / 2 - ); - if (this._clip_width >= 0 || this._clip_height >= 0) - radius = Math.min(radius, this._clip_width / 2, this._clip_height / 2); - - this.set_uniform_value('radius', parseFloat(radius - 1e-6)); - } - - get width() { - return this._width; - } - - set width(value) { - if (this._width !== value) { - this._width = value; - - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); - this.update_radius(); - } - } - - get height() { - return this._height; - } - - set height(value) { - if (this._height !== value) { - this._height = value; - - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); - this.update_radius(); - } - } - - get corners_top() { - return this._corners_top; - } - - set corners_top(value) { - if (this._corners_top !== value) { - this._corners_top = value; - - this.set_uniform_value('corners_top', this._corners_top ? 1 : 0); - } - } - - get corners_bottom() { - return this._corners_bottom; - } - - set corners_bottom(value) { - if (this._corners_bottom !== value) { - this._corners_bottom = value; - - this.set_uniform_value('corners_bottom', this._corners_bottom ? 1 : 0); - } - } - - get clip() { - return [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height]; - } - - set clip(value) { - [this._clip_x0, this._clip_y0, this._clip_width, this._clip_height] = value; - this.set_uniform_value('clip_x0', parseFloat(this._clip_x0 - 1e-6)); - this.set_uniform_value('clip_y0', parseFloat(this._clip_y0 - 1e-6)); - this.set_uniform_value('clip_width', parseFloat(this._clip_width + 3 - 1e-6)); - this.set_uniform_value('clip_height', parseFloat(this._clip_height + 3 - 1e-6)); - this.update_radius(); - } - - vfunc_set_actor(actor) { - if (this._actor_connection_size_id) { - let old_actor = this.get_actor(); - old_actor?.disconnect(this._actor_connection_size_id); - } - if (this._actor_connection_clip_rect_id) { - let old_actor = this.get_actor(); - old_actor?.disconnect(this._actor_connection_clip_rect_id); - } - - if (actor) { - this.width = actor.width; - this.height = actor.height; - this._actor_connection_size_id = actor.connect('notify::size', _ => { - this.width = actor.width; - this.height = actor.height; - }); - - this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10]; - this._actor_connection_clip_rect_id = actor.connect('notify::clip-rect', _ => { - this.clip = actor.has_clip ? actor.get_clip() : [0, 0, -10, -10]; - }); - } - else { - this._actor_connection_size_id = null; - this._actor_connection_clip_rect_id = null; - } - - super.vfunc_set_actor(actor); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - //this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/effects.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/effects.js deleted file mode 100755 index 064014cf..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/effects.js +++ /dev/null @@ -1,226 +0,0 @@ -import { NativeDynamicBlurEffect } from '../effects/native_dynamic_gaussian_blur.js'; -import { NativeStaticBlurEffect } from '../effects/native_static_gaussian_blur.js'; -import { GaussianBlurEffect } from '../effects/gaussian_blur.js'; -import { MonteCarloBlurEffect } from '../effects/monte_carlo_blur.js'; -import { ColorEffect } from '../effects/color.js'; -import { PixelizeEffect } from './pixelize.js'; -import { NoiseEffect } from '../effects/noise.js'; -import { CornerEffect } from '../effects/corner.js'; - -// We do in this way because I've not found another way to store our preferences in a dictionnary -// while calling `gettext` on it while in preferences. Not so pretty, but works. -export function get_effects_groups(_ = _ => "") { - return { - blur_effects: { - name: _("Blur effects"), - contains: [ - "native_static_gaussian_blur", - "gaussian_blur", - "monte_carlo_blur" - ] - }, - texture_effects: { - name: _("Texture effects"), - contains: [ - "pixelize", - "noise", - "color" - ] - }, - shape_effects: { - name: _("Shape effects"), - contains: [ - "corner" - ] - } - }; -}; - -export function get_supported_effects(_ = () => "") { - return { - native_dynamic_gaussian_blur: { - class: NativeDynamicBlurEffect - }, - - native_static_gaussian_blur: { - class: NativeStaticBlurEffect, - name: _("Native gaussian blur"), - description: _("An optimized blur effect that smoothly blends pixels within a given radius."), - editable_params: { - unscaled_radius: { - name: _("Radius"), - description: _("The intensity of the blur effect."), - type: "float", - min: 0., - max: 100., - increment: 1.0, - big_increment: 10., - digits: 0 - }, - brightness: { - name: _("Brightness"), - description: _("The brightness of the blur effect, a high value might make the text harder to read."), - type: "float", - min: 0., - max: 1., - increment: 0.01, - big_increment: 0.1, - digits: 2 - }, - } - }, - - gaussian_blur: { - class: GaussianBlurEffect, - name: _("Gaussian blur"), - description: _("A blur effect that smoothly blends pixels within a given radius. This effect is more precise, but way less optimized."), - editable_params: { - radius: { - name: _("Radius"), - description: _("The intensity of the blur effect. The bigger it is, the slower it will be."), - type: "float", - min: 0., - max: 100., - increment: .1, - big_increment: 10., - digits: 1 - }, - brightness: { - name: _("Brightness"), - description: _("The brightness of the blur effect, a high value might make the text harder to read."), - type: "float", - min: 0., - max: 1., - increment: 0.01, - big_increment: 0.1, - digits: 2 - }, - } - }, - - monte_carlo_blur: { - class: MonteCarloBlurEffect, - name: _("Monte Carlo blur"), - description: _("A blur effect that mimics a random walk, by picking pixels further and further away from its origin and mixing them all together."), - editable_params: { - radius: { - name: _("Radius"), - description: _("The maximum travel distance for each step in the random walk. A higher value will make the blur more randomized."), - type: "float", - min: 0., - max: 10., - increment: 0.01, - big_increment: 0.1, - digits: 2 - }, - iterations: { - name: _("Iterations"), - description: _("The number of iterations. The more there are, the smoother the blur is."), - type: "integer", - min: 0, - max: 50, - increment: 1 - }, - brightness: { - name: _("Brightness"), - description: _("The brightness of the blur effect, a high value might make the text harder to read."), - type: "float", - min: 0., - max: 1., - increment: 0.01, - big_increment: 0.1, - digits: 2 - }, - use_base_pixel: { - name: _("Use base pixel"), - description: _("Whether or not the original pixel is counted for the blur. If it is, the image will be more legible."), - type: "boolean" - } - } - }, - - color: { - class: ColorEffect, - name: _("Color"), - description: _("An effect that blends a color into the pipeline."), - // TODO make this RGB + blend - editable_params: { - color: { - name: _("Color"), - description: _("The color to blend in. The blending amount is controled by the opacity of the color."), - type: "rgba" - } - } - }, - - pixelize: { - class: PixelizeEffect, - name: _("Pixelize"), - description: _("An effect that pixelizes the image."), - editable_params: { - divider: { - name: _("Divider"), - description: _("How much to scale down the image."), - type: "integer", - min: 1, - max: 50, - increment: 1 - } - } - }, - - noise: { - class: NoiseEffect, - name: _("Noise"), - description: _("An effect that adds a random noise. Prefer the Monte Carlo blur for a more organic effect if needed."), - editable_params: { - noise: { - name: _("Noise"), - description: _("The amount of noise to add."), - type: "float", - min: 0., - max: 1., - increment: 0.01, - big_increment: 0.1, - digits: 2 - }, - lightness: { - name: _("Lightness"), - description: _("The luminosity of the noise. A setting of '1.0' will make the effect transparent."), - type: "float", - min: 0., - max: 2., - increment: 0.01, - big_increment: 0.1, - digits: 2 - } - } - }, - - corner: { - class: CornerEffect, - name: _("Corner"), - description: _("An effect that draws corners. Add it last not to have the other effects perturb the corners."), - editable_params: { - radius: { - name: _("Radius"), - description: _("The radius of the corner. GNOME apps use a radius of 12 px by default."), - type: "integer", - min: 0, - max: 50, - increment: 1, - }, - corners_top: { - name: _("Top corners"), - description: _("Whether or not to round the top corners."), - type: "boolean" - }, - corners_bottom: { - name: _("Bottom corners"), - description: _("Whether or not to round the bottom corners."), - type: "boolean" - } - } - } - }; -}; \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/gaussian_blur.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/gaussian_blur.glsl deleted file mode 100755 index 809cc93d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/gaussian_blur.glsl +++ /dev/null @@ -1,70 +0,0 @@ -uniform sampler2D tex; -uniform float sigma; -uniform int dir; -uniform float brightness; -uniform float width; -uniform float height; - -vec4 getTexture(vec2 uv) { - if (uv.x < 3. / width) - uv.x = 3. / width; - - if (uv.y < 3. / height) - uv.y = 3. / height; - - if (uv.x > 1. - 3. / width) - uv.x = 1. - 3. / width; - - if (uv.y > 1. - 3. / height) - uv.y = 1. - 3. / height; - - return texture2D(tex, uv); -} - -void main(void) { - vec2 uv = cogl_tex_coord_in[0].xy; - vec2 direction = vec2(dir, (1.0 - dir)); - - float pixel_step; - if (dir == 0) - pixel_step = 1.0 / height; - else - pixel_step = 1.0 / width; - - vec3 gauss_coefficient; - gauss_coefficient.x = 1.0 / (sqrt(2.0 * 3.14159265) * sigma); - gauss_coefficient.y = exp(-0.5 / (sigma * sigma)); - gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y; - - float gauss_coefficient_total = gauss_coefficient.x; - - vec4 ret = getTexture(uv) * gauss_coefficient.x; - gauss_coefficient.xy *= gauss_coefficient.yz; - - int n_steps = int(ceil(1.5 * sigma)) * 2; - - for (int i = 1; i <= n_steps; i += 2) { - float coefficient_subtotal = gauss_coefficient.x; - gauss_coefficient.xy *= gauss_coefficient.yz; - coefficient_subtotal += gauss_coefficient.x; - - float gauss_ratio = gauss_coefficient.x / coefficient_subtotal; - - float foffset = float(i) + gauss_ratio; - vec2 offset = direction * foffset * pixel_step; - - ret += getTexture(uv + offset) * coefficient_subtotal; - ret += getTexture(uv - offset) * coefficient_subtotal; - - gauss_coefficient_total += 2.0 * coefficient_subtotal; - gauss_coefficient.xy *= gauss_coefficient.yz; - } - vec4 outColor = ret / gauss_coefficient_total; - - // apply brightness on the second pass (dir==0 comes last) - if (dir == 0) { - outColor.rgb *= brightness; - } - - cogl_color_out = outColor; -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/gaussian_blur.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/gaussian_blur.js deleted file mode 100755 index dc3e637e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/gaussian_blur.js +++ /dev/null @@ -1,227 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const St = await utils.import_in_shell_only('gi://St'); -const Shell = await utils.import_in_shell_only('gi://Shell'); -const Clutter = await utils.import_in_shell_only('gi://Clutter'); - -const SHADER_FILENAME = 'gaussian_blur.glsl'; -const DEFAULT_PARAMS = { - radius: 30, brightness: .6, - width: 0, height: 0, direction: 0 -}; - - -export const GaussianBlurEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "GaussianBlurEffect", - Properties: { - 'radius': GObject.ParamSpec.double( - `radius`, - `Radius`, - `Blur radius`, - GObject.ParamFlags.READWRITE, - 0.0, 2000.0, - 30.0, - ), - 'brightness': GObject.ParamSpec.double( - `brightness`, - `Brightness`, - `Blur brightness`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.6, - ), - 'width': GObject.ParamSpec.double( - `width`, - `Width`, - `Width`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'height': GObject.ParamSpec.double( - `height`, - `Height`, - `Height`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'direction': GObject.ParamSpec.int( - `direction`, - `Direction`, - `Direction`, - GObject.ParamFlags.READWRITE, - 0, 1, - 0, - ), - 'chained_effect': GObject.ParamSpec.object( - `chained_effect`, - `Chained Effect`, - `Chained Effect`, - GObject.ParamFlags.READABLE, - GObject.Object, - ), - } - }, class GaussianBlurEffect extends Clutter.ShaderEffect { - constructor(params) { - super(params); - - this._radius = null; - this._brightness = null; - this._width = null; - this._height = null; - this._direction = null; - - this._chained_effect = null; - - this.radius = 'radius' in params ? params.radius : this.constructor.default_params.radius; - this.brightness = 'brightness' in params ? params.brightness : this.constructor.default_params.brightness; - this.width = 'width' in params ? params.width : this.constructor.default_params.width; - this.height = 'height' in params ? params.height : this.constructor.default_params.height; - this.direction = 'direction' in params ? params.direction : this.constructor.default_params.direction; - - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); - - const theme_context = St.ThemeContext.get_for_stage(global.stage); - theme_context.connectObject( - 'notify::scale-factor', _ => - this.set_uniform_value('sigma', - parseFloat(this.radius * theme_context.scale_factor / 2 - 1e-6) - ), - this - ); - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get radius() { - return this._radius; - } - - set radius(value) { - if (this._radius !== value) { - this._radius = value; - - const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - - // like Clutter, we use the assumption radius = 2*sigma - this.set_uniform_value('sigma', parseFloat(this._radius * scale_factor / 2 - 1e-6)); - this.set_enabled(this.radius > 0.); - - if (this._chained_effect) - this._chained_effect.radius = value; - } - } - - get brightness() { - return this._brightness; - } - - set brightness(value) { - if (this._brightness !== value) { - this._brightness = value; - - this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); - - if (this._chained_effect) - this._chained_effect.brightness = value; - } - } - - get width() { - return this._width; - } - - set width(value) { - if (this._width !== value) { - this._width = value; - - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); - - if (this._chained_effect) - this._chained_effect.width = value; - } - } - - get height() { - return this._height; - } - - set height(value) { - if (this._height !== value) { - this._height = value; - - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); - - if (this._chained_effect) - this._chained_effect.height = value; - } - } - - get direction() { - return this._direction; - } - - set direction(value) { - if (this._direction !== value) - this._direction = value; - } - - get chained_effect() { - return this._chained_effect; - } - - vfunc_set_actor(actor) { - if (this._actor_connection_size_id) { - let old_actor = this.get_actor(); - old_actor?.disconnect(this._actor_connection_size_id); - } - if (actor) { - this.width = actor.width; - this.height = actor.height; - this._actor_connection_size_id = actor.connect('notify::size', _ => { - this.width = actor.width; - this.height = actor.height; - }); - } - else - this._actor_connection_size_id = null; - - super.vfunc_set_actor(actor); - - if (this.direction == 0) { - if (this.chained_effect) - this._chained_effect.get_actor()?.remove_effect(this._chained_effect); - else - this._chained_effect = new GaussianBlurEffect({ - radius: this.radius, - brightness: this.brightness, - width: this.width, - height: this.height, - direction: 1 - }); - if (actor !== null) - actor.add_effect(this._chained_effect); - } - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - //this.set_uniform_value("tex", 0); - this.set_uniform_value("dir", this._direction); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl deleted file mode 100755 index 4142a467..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/monte_carlo_blur.glsl +++ /dev/null @@ -1,44 +0,0 @@ -uniform sampler2D tex; -uniform float radius; -uniform int iterations; -uniform float brightness; -uniform float width; -uniform float height; -uniform bool use_base_pixel; - -float srand(vec2 a) { - return sin(dot(a, vec2(1233.224, 1743.335))); -} - -float rand(inout float r) { - r = fract(3712.65 * r + 0.61432); - return (r - 0.5) * 2.0; -} - -void main() { - vec2 uv = cogl_tex_coord0_in.st; - vec2 p = 16 * radius / vec2(width, height); - float r = srand(uv); - vec2 rv; - - int count = 0; - vec4 c = vec4(0.); - - for (int i = 0; i < iterations; i++) { - rv.x = rand(r); - rv.y = rand(r); - vec2 new_uv = uv + rv * p; - if (new_uv.x > 2. / width && new_uv.y > 2. / height && new_uv.x < 1. - 3. / width && new_uv.y < 1. - 3. / height) { - c += texture2D(tex, new_uv); - count += 1; - } - } - - if (count == 0 || use_base_pixel) { - c += texture2D(tex, uv); - count += 1; - } - - c.xyz *= brightness; - cogl_color_out = c / count; -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/monte_carlo_blur.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/monte_carlo_blur.js deleted file mode 100755 index 20b7bfbe..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/monte_carlo_blur.js +++ /dev/null @@ -1,211 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const St = await utils.import_in_shell_only('gi://St'); -const Shell = await utils.import_in_shell_only('gi://Shell'); -const Clutter = await utils.import_in_shell_only('gi://Clutter'); - -const SHADER_FILENAME = 'monte_carlo_blur.glsl'; -const DEFAULT_PARAMS = { - radius: 2., iterations: 5, brightness: .6, - width: 0, height: 0, use_base_pixel: true -}; - - -export const MonteCarloBlurEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "MonteCarloBlurEffect", - Properties: { - 'radius': GObject.ParamSpec.double( - `radius`, - `Radius`, - `Blur radius`, - GObject.ParamFlags.READWRITE, - 0.0, 2000.0, - 2.0, - ), - 'iterations': GObject.ParamSpec.int( - `iterations`, - `Iterations`, - `Blur iterations`, - GObject.ParamFlags.READWRITE, - 0, 64, - 5, - ), - 'brightness': GObject.ParamSpec.double( - `brightness`, - `Brightness`, - `Blur brightness`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.6, - ), - 'width': GObject.ParamSpec.double( - `width`, - `Width`, - `Width`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'height': GObject.ParamSpec.double( - `height`, - `Height`, - `Height`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'use_base_pixel': GObject.ParamSpec.boolean( - `use_base_pixel`, - `Use base pixel`, - `Use base pixel`, - GObject.ParamFlags.READWRITE, - true, - ), - } - }, class MonteCarloBlurEffect extends Clutter.ShaderEffect { - constructor(params) { - super(params); - - this._radius = null; - this._iterations = null; - this._brightness = null; - this._width = null; - this._height = null; - this._use_base_pixel = null; - - this.radius = 'radius' in params ? params.radius : this.constructor.default_params.radius; - this.iterations = 'iterations' in params ? params.iterations : this.constructor.default_params.iterations; - this.brightness = 'brightness' in params ? params.brightness : this.constructor.default_params.brightness; - this.width = 'width' in params ? params.width : this.constructor.default_params.width; - this.height = 'height' in params ? params.height : this.constructor.default_params.height; - this.use_base_pixel = 'use_base_pixel' in params ? params.use_base_pixel : this.constructor.default_params.use_base_pixel; - - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); - - const theme_context = St.ThemeContext.get_for_stage(global.stage); - theme_context.connectObject( - 'notify::scale-factor', - _ => this.set_uniform_value('radius', - parseFloat(this._radius * theme_context.scale_factor - 1e-6) - ), - this - ); - - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get radius() { - return this._radius; - } - - set radius(value) { - if (this._radius !== value) { - this._radius = value; - - const scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - - this.set_uniform_value('radius', parseFloat(this._radius * scale_factor - 1e-6)); - this.set_enabled(this.radius > 0. && this.iterations > 0); - } - } - - get iterations() { - return this._iterations; - } - - set iterations(value) { - if (this._iterations !== value) { - this._iterations = value; - - this.set_uniform_value('iterations', this._iterations); - this.set_enabled(this.radius > 0. && this.iterations > 0); - } - } - - get brightness() { - return this._brightness; - } - - set brightness(value) { - if (this._brightness !== value) { - this._brightness = value; - - this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); - } - } - - get width() { - return this._width; - } - - set width(value) { - if (this._width !== value) { - this._width = value; - - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); - } - } - - get height() { - return this._height; - } - - set height(value) { - if (this._height !== value) { - this._height = value; - - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); - } - } - - get use_base_pixel() { - return this._use_base_pixel; - } - - set use_base_pixel(value) { - if (this._use_base_pixel !== value) { - this._use_base_pixel = value; - - this.set_uniform_value('use_base_pixel', this._use_base_pixel ? 1 : 0); - } - } - - vfunc_set_actor(actor) { - if (this._actor_connection_size_id) { - let old_actor = this.get_actor(); - old_actor?.disconnect(this._actor_connection_size_id); - } - if (actor) { - this.width = actor.width; - this.height = actor.height; - this._actor_connection_size_id = actor.connect('notify::size', _ => { - this.width = actor.width; - this.height = actor.height; - }); - } - else - this._actor_connection_size_id = null; - - super.vfunc_set_actor(actor); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - //this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js deleted file mode 100755 index 2ef1f1ae..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/native_dynamic_gaussian_blur.js +++ /dev/null @@ -1,44 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const St = await utils.import_in_shell_only('gi://St'); -const Shell = await utils.import_in_shell_only('gi://Shell'); - -const DEFAULT_PARAMS = { - unscaled_radius: 30, brightness: 0.6 -}; - - -export const NativeDynamicBlurEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "NativeDynamicBlurEffect" - }, class NativeDynamicBlurEffect extends Shell.BlurEffect { - constructor(params) { - const { unscaled_radius, ...parent_params } = params; - super({ ...parent_params, mode: Shell.BlurMode.BACKGROUND }); - - this._theme_context = St.ThemeContext.get_for_stage(global.stage); - - this.unscaled_radius = 'unscaled_radius' in params ? unscaled_radius : this.constructor.default_params.unscaled_radius; - - this._theme_context.connectObject( - 'notify::scale-factor', - _ => this.radius = this.unscaled_radius * this._theme_context.scale_factor, - this - ); - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get unscaled_radius() { - return this._unscaled_radius; - } - - set unscaled_radius(value) { - this._unscaled_radius = value; - this.radius = value * this._theme_context.scale_factor; - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js deleted file mode 100755 index ff99654d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/native_static_gaussian_blur.js +++ /dev/null @@ -1,44 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const St = await utils.import_in_shell_only('gi://St'); -const Shell = await utils.import_in_shell_only('gi://Shell'); - -const DEFAULT_PARAMS = { - unscaled_radius: 30, brightness: 0.6 -}; - - -export const NativeStaticBlurEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "NativeStaticBlurEffect" - }, class NativeStaticBlurEffect extends Shell.BlurEffect { - constructor(params) { - const { unscaled_radius, ...parent_params } = params; - super({ ...parent_params, mode: Shell.BlurMode.ACTOR }); - - this._theme_context = St.ThemeContext.get_for_stage(global.stage); - - this.unscaled_radius = 'unscaled_radius' in params ? unscaled_radius : this.constructor.default_params.unscaled_radius; - - this._theme_context.connectObject( - 'notify::scale-factor', - _ => this.radius = this.unscaled_radius * this._theme_context.scale_factor, - this - ); - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get unscaled_radius() { - return this._unscaled_radius; - } - - set unscaled_radius(value) { - this._unscaled_radius = value; - this.radius = value * this._theme_context.scale_factor; - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/noise.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/noise.glsl deleted file mode 100755 index 6d701b60..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/noise.glsl +++ /dev/null @@ -1,20 +0,0 @@ -uniform sampler2D tex; -uniform float noise; -uniform float lightness; - -float PHI = 1.61803398874989484820459; -float SEED = 24; - -float noise_gen(in vec2 xy) { - float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x); - r = r != r ? 0.0 : r; - return r; -} - -void main() { - vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); - vec3 pix_color = c.xyz; - float blend = noise * (1. - noise_gen(gl_FragCoord.xy)); - - cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/noise.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/noise.js deleted file mode 100755 index 1ddfb215..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/noise.js +++ /dev/null @@ -1,91 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const Shell = await utils.import_in_shell_only('gi://Shell'); -const Clutter = await utils.import_in_shell_only('gi://Clutter'); - -const SHADER_FILENAME = 'noise.glsl'; -const DEFAULT_PARAMS = { - noise: 0.4, lightness: 0.4 -}; - - -export const NoiseEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "NoiseEffect", - Properties: { - 'noise': GObject.ParamSpec.double( - `noise`, - `Noise`, - `Amount of noise integrated with the image`, - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 0.4, - ), - 'lightness': GObject.ParamSpec.double( - `lightness`, - `Lightness`, - `Lightness of the grey used for the noise`, - GObject.ParamFlags.READWRITE, - 0.0, 2.0, - 0.4, - ), - } - }, class NoiseEffect extends Clutter.ShaderEffect { - constructor(params) { - super(params); - - this._noise = null; - this._lightness = null; - - this.noise = 'noise' in params ? params.noise : this.constructor.default_params.noise; - this.lightness = 'lightness' in params ? params.lightness : this.constructor.default_params.lightness; - - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get noise() { - return this._noise; - } - - set noise(value) { - if (this._noise !== value) { - this._noise = value; - - this.set_uniform_value('noise', parseFloat(this._noise - 1e-6)); - this.set_enabled(this.noise > 0. && this.lightness != 1); - } - } - - get lightness() { - return this._lightness; - } - - set lightness(value) { - if (this._lightness !== value) { - this._lightness = value; - - this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6)); - this.set_enabled(this.noise > 0. && this.lightness != 1); - } - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/pixelize.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/pixelize.glsl deleted file mode 100755 index e7ac9530..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/pixelize.glsl +++ /dev/null @@ -1,27 +0,0 @@ -uniform sampler2D tex; -uniform int divider; -uniform float width; -uniform float height; - -vec4 getTexture(vec2 uv) { - if (uv.x < 3. / width) - uv.x = 3. / width; - - if (uv.y < 3. / height) - uv.y = 3. / height; - - if (uv.x > 1. - 3. / width) - uv.x = 1. - 3. / width; - - if (uv.y > 1. - 3. / height) - uv.y = 1. - 3. / height; - - return texture2D(tex, uv); -} - -void main() { - vec2 uv = cogl_tex_coord0_in.st; - vec2 scaled_multiplier = vec2(width, height) / divider; - vec2 new_uv = 0.5 + floor((uv - 0.5) * scaled_multiplier) / scaled_multiplier; - cogl_color_out = getTexture(new_uv); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/pixelize.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/pixelize.js deleted file mode 100755 index e6a35915..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/effects/pixelize.js +++ /dev/null @@ -1,130 +0,0 @@ -import GObject from 'gi://GObject'; - -import * as utils from '../conveniences/utils.js'; -const Shell = await utils.import_in_shell_only('gi://Shell'); -const Clutter = await utils.import_in_shell_only('gi://Clutter'); - -const SHADER_FILENAME = 'pixelize.glsl'; -const DEFAULT_PARAMS = { - divider: 8, width: 0, height: 0 -}; - - -export const PixelizeEffect = utils.IS_IN_PREFERENCES ? - { default_params: DEFAULT_PARAMS } : - new GObject.registerClass({ - GTypeName: "PixelizeEffect", - Properties: { - 'divider': GObject.ParamSpec.int( - `divider`, - `Divider`, - `Divider`, - GObject.ParamFlags.READWRITE, - 0, 64, - 5, - ), - 'width': GObject.ParamSpec.double( - `width`, - `Width`, - `Width`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ), - 'height': GObject.ParamSpec.double( - `height`, - `Height`, - `Height`, - GObject.ParamFlags.READWRITE, - 0.0, Number.MAX_SAFE_INTEGER, - 0.0, - ) - } - }, class PixelizeEffect extends Clutter.ShaderEffect { - constructor(params) { - super(params); - - this._divider = null; - this._width = null; - this._height = null; - - this.divider = 'divider' in params ? params.divider : this.constructor.default_params.divider; - this.width = 'width' in params ? params.width : this.constructor.default_params.width; - this.height = 'height' in params ? params.height : this.constructor.default_params.height; - - // set shader source - this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); - if (this._source) - this.set_shader_source(this._source); - } - - static get default_params() { - return DEFAULT_PARAMS; - } - - get divider() { - return this._width; - } - - set divider(value) { - if (this._divider !== value) { - this._divider = value; - - this.set_uniform_value('divider', this._divider); - } - } - - get width() { - return this._width; - } - - set width(value) { - if (this._width !== value) { - this._width = value; - - this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); - } - } - - get height() { - return this._height; - } - - set height(value) { - if (this._height !== value) { - this._height = value; - - this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); - } - } - - vfunc_set_actor(actor) { - if (this._actor_connection_size_id) { - let old_actor = this.get_actor(); - old_actor?.disconnect(this._actor_connection_size_id); - } - if (actor) { - this.width = actor.width; - this.height = actor.height; - this._actor_connection_size_id = actor.connect('notify::size', _ => { - this.width = actor.width; - this.height = actor.height; - }); - } - else - this._actor_connection_size_id = null; - - super.vfunc_set_actor(actor); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - //this.set_uniform_value("tex", 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) - super.vfunc_paint_target(paint_node); - else - super.vfunc_paint_target(); - } - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/extension.js deleted file mode 100755 index d789eb2f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/extension.js +++ /dev/null @@ -1,570 +0,0 @@ -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import { update_from_old_settings } from './conveniences/settings_updater.js'; -import { PipelinesManager } from './conveniences/pipelines_manager.js'; -import { EffectsManager } from './conveniences/effects_manager.js'; -import { Connections } from './conveniences/connections.js'; -import { Settings } from './conveniences/settings.js'; -import { KEYS } from './conveniences/keys.js'; - -import { PanelBlur } from './components/panel.js'; -import { OverviewBlur } from './components/overview.js'; -import { DashBlur } from './components/dash_to_dock.js'; -import { LockscreenBlur } from './components/lockscreen.js'; -import { AppFoldersBlur } from './components/appfolders.js'; -import { WindowListBlur } from './components/window_list.js'; -import { ApplicationsBlur } from './components/applications.js'; -import { ScreenshotBlur } from './components/screenshot.js'; - - -/// The main extension class, created when the GNOME Shell is loaded. -export default class BlurMyShell extends Extension { - /// Enables the extension. - enable() { - // add the extension to global to make it accessible to other extensions - // create it first as it is very useful when debugging crashes - global.blur_my_shell = this; - - // update from old settings, very important for hacks level specifically - update_from_old_settings(this.getSettings()); - - // create a Settings instance, to manage extension's preferences - // it needs to be loaded before logging, as it checks for DEBUG - this._settings = new Settings(KEYS, this.getSettings()); - - this._log("enabling extension..."); - - // create main extension Connections instance - this._connection = new Connections; - - // store it in a global array - this._connections = [this._connection]; - - // create a global effects manager (to prevent RAM bleeding) - this._effects_manager = new EffectsManager(this._connection); - - // create a global pipelines manager, that helps talking with preferences - this._pipelines_manager = new PipelinesManager(this._settings); - - // create an instance of each component, with its associated Connections - let init = () => { - // create a Connections instance, to manage signals - let connection = new Connections; - - // store it to keeps track of them globally - this._connections.push(connection); - - return [connection, this._settings, this._effects_manager]; - }; - - this._panel_blur = new PanelBlur(...init()); - this._dash_to_dock_blur = new DashBlur(...init()); - this._overview_blur = new OverviewBlur(...init()); - this._lockscreen_blur = new LockscreenBlur(...init()); - this._appfolder_blur = new AppFoldersBlur(...init()); - this._window_list_blur = new WindowListBlur(...init()); - this._applications_blur = new ApplicationsBlur(...init()); - this._screenshot_blur = new ScreenshotBlur(...init()); - - // connect each component to preferences change - this._connect_to_settings(); - - // enable the lockscreen blur, only one important in both `user` session and `unlock-dialog` - if (this._settings.lockscreen.BLUR && !this._lockscreen_blur.enabled) - this._lockscreen_blur.enable(); - - // ensure we take the correct action for the current session mode - this._user_session_mode_enabled = false; - this._on_session_mode_changed(Main.sessionMode); - - // watch for changes to the session mode - this._connection.connect(Main.sessionMode, 'updated', - () => this._on_session_mode_changed(Main.sessionMode) - ); - } - - /// Enables the components related to the user session (everything except lockscreen blur). - _enable_user_session() { - this._log("changing mode to user session..."); - - // maybe disable clipped redraw - this._update_clipped_redraws(); - - // enable every component - // if the shell is still starting up, wait for it to be entirely loaded; - // this should prevent bugs like #136 and #137 - if (Main.layoutManager._startingUp) { - this._connection.connect( - Main.layoutManager, - 'startup-complete', - () => this._enable_components() - ); - } else - this._enable_components(); - - // try to enable the components as soon as possible anyway, this way the - // overview may load before the user sees it - try { - if (this._settings.overview.BLUR && !this._overview_blur.enabled) - this._overview_blur.enable(); - } catch (e) { - this._log("Could not enable overview blur directly"); - this._log(e); - } - try { - if (this._settings.dash_to_dock.BLUR - && !this._dash_to_dock_blur.enabled) - this._dash_to_dock_blur.enable(); - } catch (e) { - this._log("Could not enable dash-to-dock blur directly"); - this._log(e); - } - try { - if (this._settings.panel.BLUR && !this._panel_blur.enabled) - this._panel_blur.enable(); - } catch (e) { - this._log("Could not enable panel blur directly"); - this._log(e); - } - - // tells the extension we have enabled the user session components, so that we do not - // disable them later if they were not even enabled to begin with - this._user_session_mode_enabled = true; - } - - /// Disables the extension. - /// - /// This extension needs to use the 'unlock-dialog' session mode in order to change the blur on - /// the lockscreen. We have kind of two states of enablement for this extension: - /// - the 'enabled' state, which means that we have created the necessary components (which only - /// are js objects) and enabled the lockscreen blur (which means swapping two functions from - /// the `UnlockDialog` constructor with our ones; - /// - the 'user session enabled` mode, which means that we are in the 'enabled' mode AND we are - /// in the user mode, and so we enable all the other components that we created before. - /// We switch from one state to the other thanks to `this._on_session_mode_changed`, and we - /// track wether or not we are in the user mode with `this._user_session_mode_enabled` (because - /// `this._on_session_mode_changed` might be called multiple times while in the user session - /// mode, typically when going back from simple lockscreen and not sleep mode). - disable() { - this._log("disabling extension..."); - - // disable every component from user session mode - if (this._user_session_mode_enabled) - this._disable_user_session(); - - // disable lockscreen blur too - this._lockscreen_blur.disable(); - - // untrack them - this._panel_blur = null; - this._dash_to_dock_blur = null; - this._overview_blur = null; - this._appfolder_blur = null; - this._lockscreen_blur = null; - this._window_list_blur = null; - this._applications_blur = null; - this._screenshot_blur = null; - - // make sure no settings change can re-enable them - this._settings.disconnect_all_settings(); - - // force disconnecting every signal, even if component crashed - this._connections.forEach((connections) => { - connections.disconnect_all(); - }); - this._connections = []; - - // remove the clipped redraws flag - this._reenable_clipped_redraws(); - - // remove the extension from GJS's global - delete global.blur_my_shell; - - this._log("extension disabled."); - - this._settings = null; - } - - /// Disables the components related to the user session (everything except lockscreen blur). - _disable_user_session() { - this._log("disabling user session mode..."); - - // disable every component except lockscreen blur - this._panel_blur.disable(); - this._dash_to_dock_blur.disable(); - this._overview_blur.disable(); - this._appfolder_blur.disable(); - this._window_list_blur.disable(); - this._applications_blur.disable(); - this._screenshot_blur.disable(); - - // remove the clipped redraws flag - this._reenable_clipped_redraws(); - - // tells the extension we have disabled the user session components, so that we do not - // disable them later again if they were already disabled - this._user_session_mode_enabled = false; - } - - /// Restarts the components related to the user session. - _restart() { - this._log("restarting..."); - - this._disable_user_session(); - this._enable_user_session(); - - this._log("restarted."); - } - - /// Changes the extension to operate either on 'user' mode or 'unlock-dialog' mode, switching - /// from one to the other means enabling/disabling every component except lockscreen blur. - _on_session_mode_changed(session) { - if (session.currentMode === 'user' || session.parentMode === 'user') { - if (!this._user_session_mode_enabled) - // we need to activate everything - this._enable_user_session(); - } - else if (session.currentMode === 'unlock-dialog') { - if (this._user_session_mode_enabled) - // we need to disable the components related to the user session mode - this._disable_user_session(); - } - } - - /// Add or remove the clutter debug flag to disable clipped redraws. - /// This will entirely fix the blur effect, but should not be used except if - /// the user really needs it, as clipped redraws are a huge performance - /// boost for the compositor. - _update_clipped_redraws() { - if (this._settings.HACKS_LEVEL === 2) - this._disable_clipped_redraws(); - else - this._reenable_clipped_redraws(); - } - - /// Add the Clutter debug flag. - _disable_clipped_redraws() { - Meta.add_clutter_debug_flags( - null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null - ); - } - - /// Remove the Clutter debug flag. - _reenable_clipped_redraws() { - Meta.remove_clutter_debug_flags( - null, Clutter.DrawDebugFlag.DISABLE_CLIPPED_REDRAWS, null - ); - } - - /// Enables every component from the user session needed, should be called when the shell is - /// entirely loaded as the `enable` methods interact with it. - _enable_components() { - // enable each component if needed, and if it is not already enabled - - if (this._settings.panel.BLUR && !this._panel_blur.enabled) - this._panel_blur.enable(); - - if (this._settings.dash_to_dock.BLUR && !this._dash_to_dock_blur.enabled) - this._dash_to_dock_blur.enable(); - - if (this._settings.overview.BLUR && !this._overview_blur.enabled) - this._overview_blur.enable(); - - if (this._settings.appfolder.BLUR) - this._appfolder_blur.enable(); - - if (this._settings.applications.BLUR) - this._applications_blur.enable(); - - if (this._settings.window_list.BLUR) - this._window_list_blur.enable(); - - if (this._settings.screenshot.BLUR) - this._screenshot_blur.enable(); - - this._log("all components enabled."); - } - - /// Updates needed things in each component when a preference changed - _connect_to_settings() { - // restart the extension when hacks level is changed, easier than - // restarting individual components and should not happen often either - this._settings.HACKS_LEVEL_changed(() => this._restart()); - - - // ---------- OVERVIEW ---------- - - // toggled on/off - this._settings.overview.BLUR_changed(() => { - if (this._settings.overview.BLUR) - this._overview_blur.enable(); - else - this._overview_blur.disable(); - }); - - // overview pipeline changed - this._settings.overview.PIPELINE_changed(() => { - if (this._settings.overview.BLUR) - this._overview_blur.update_backgrounds(); - }); - - // overview components style changed - this._settings.overview.STYLE_COMPONENTS_changed(() => { - if (this._settings.overview.BLUR) - this._overview_blur.update_components_classname(); - }); - - - // ---------- APPFOLDER ---------- - - // toggled on/off - this._settings.appfolder.BLUR_changed(() => { - if (this._settings.appfolder.BLUR) - this._appfolder_blur.enable(); - else - this._appfolder_blur.disable(); - }); - - // appfolder sigma changed - this._settings.appfolder.SIGMA_changed(() => { - if (this._settings.appfolder.BLUR) - this._appfolder_blur.set_sigma( - this._settings.appfolder.SIGMA - ); - }); - - // appfolder brightness changed - this._settings.appfolder.BRIGHTNESS_changed(() => { - if (this._settings.appfolder.BLUR) - this._appfolder_blur.set_brightness( - this._settings.appfolder.BRIGHTNESS - ); - }); - - // appfolder dialogs style changed - this._settings.appfolder.STYLE_DIALOGS_changed(() => { - if (this._settings.appfolder.BLUR) - this._appfolder_blur.blur_appfolders(); - }); - - - // ---------- PANEL ---------- - - // toggled on/off - this._settings.panel.BLUR_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.enable(); - else - this._panel_blur.disable(); - }); - - // static blur toggled on/off, really we can just reload the blur at this point - this._settings.panel.STATIC_BLUR_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.reset(); - }); - - // panel pipeline changed - this._settings.panel.PIPELINE_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.update_pipeline(); - }); - - // panel blur's overview connection toggled on/off - this._settings.panel.UNBLUR_IN_OVERVIEW_changed(() => { - this._panel_blur.connect_to_windows_and_overview(); - }); - - // force light text toggled on/off - this._settings.panel.FORCE_LIGHT_TEXT_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.update_light_text_classname(); - }); - - // panel override background toggled on/off - this._settings.panel.OVERRIDE_BACKGROUND_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.connect_to_windows_and_overview(); - }); - - // panel style changed - this._settings.panel.STYLE_PANEL_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.connect_to_windows_and_overview(); - }); - - // panel background's dynamic overriding toggled on/off - this._settings.panel.OVERRIDE_BACKGROUND_DYNAMICALLY_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.connect_to_windows_and_overview(); - }); - - - // ---------- DASH TO DOCK ---------- - - // toggled on/off - this._settings.dash_to_dock.BLUR_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.enable(); - else - this._dash_to_dock_blur.disable(); - }); - - // static blur toggled on/off - this._settings.dash_to_dock.STATIC_BLUR_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.change_blur_type(); - }); - - // overview pipeline changed - this._settings.dash_to_dock.PIPELINE_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.update_pipeline(); - }); - - // dash-to-dock override background toggled on/off - this._settings.dash_to_dock.OVERRIDE_BACKGROUND_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.update_background(); - }); - - // dash-to-dock style changed - this._settings.dash_to_dock.STYLE_DASH_TO_DOCK_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.update_background(); - }); - - // dash-to-dock blur's overview connection toggled on/off - this._settings.dash_to_dock.UNBLUR_IN_OVERVIEW_changed(() => { - if (this._settings.dash_to_dock.BLUR) - this._dash_to_dock_blur.connect_to_overview(); - }); - - - // ---------- APPLICATIONS ---------- - - // toggled on/off - this._settings.applications.BLUR_changed(() => { - if (this._settings.applications.BLUR) - this._applications_blur.enable(); - else - this._applications_blur.disable(); - }); - - // application opacity changed - this._settings.applications.OPACITY_changed(() => { - if (this._settings.applications.BLUR) - this._applications_blur.set_opacity( - this._settings.applications.OPACITY - ); - }); - - // application dynamic-opacity changed - this._settings.applications.DYNAMIC_OPACITY_changed(() => { - if (this._settings.applications.BLUR) - this._applications_blur.init_dynamic_opacity(); - }); - - // application blur-on-overview changed - this._settings.applications.BLUR_ON_OVERVIEW_changed(() => { - if (this._settings.applications.BLUR) - this._applications_blur.connect_to_overview(); - }); - - // application enable-all changed - this._settings.applications.ENABLE_ALL_changed(() => { - if (this._settings.applications.BLUR) - this._applications_blur.update_all_windows(); - }); - - // application whitelist changed - this._settings.applications.WHITELIST_changed(() => { - if ( - this._settings.applications.BLUR - && !this._settings.applications.ENABLE_ALL - ) - this._applications_blur.update_all_windows(); - }); - - // application blacklist changed - this._settings.applications.BLACKLIST_changed(() => { - if ( - this._settings.applications.BLUR - && this._settings.applications.ENABLE_ALL - ) - this._applications_blur.update_all_windows(); - }); - - - // ---------- LOCKSCREEN ---------- - - // toggled on/off - this._settings.lockscreen.BLUR_changed(() => { - if (this._settings.lockscreen.BLUR) - this._lockscreen_blur.enable(); - else - this._lockscreen_blur.disable(); - }); - - // lockscreen pipeline changed - this._settings.lockscreen.PIPELINE_changed(() => { - if (this._settings.lockscreen.BLUR) - this._lockscreen_blur.update_lockscreen(); - }); - - - // ---------- WINDOW LIST ---------- - - // toggled on/off - this._settings.window_list.BLUR_changed(() => { - if (this._settings.window_list.BLUR) - this._window_list_blur.enable(); - else - this._window_list_blur.disable(); - }); - - - // ---------- HIDETOPBAR ---------- - - // toggled on/off - this._settings.hidetopbar.COMPATIBILITY_changed(() => { - // no need to verify if it is enabled or not, it is done anyway - this._panel_blur.connect_to_windows_and_overview(); - }); - - - // ---------- DASH TO PANEL ---------- - - // toggled on/off - this._settings.dash_to_panel.BLUR_ORIGINAL_PANEL_changed(() => { - if (this._settings.panel.BLUR) - this._panel_blur.reset(); - }); - - - // ---------- SCREENSHOT ---------- - - // toggled on/off - this._settings.screenshot.BLUR_changed(() => { - if (this._settings.screenshot.BLUR) - this._screenshot_blur.enable(); - else - this._screenshot_blur.disable(); - }); - - // screenshot pipeline changed - this._settings.screenshot.PIPELINE_changed(() => { - if (this._settings.screenshot.BLUR) - this._screenshot_blur.update_pipeline(); - }); - } - - _log(str) { - if (this._settings.DEBUG) - console.log(`[Blur my Shell > extension] ${str}`); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg deleted file mode 100755 index bdab3095..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/add-row-symbolic.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg deleted file mode 100755 index 87f307f5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/applications-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg deleted file mode 100755 index 2eda98b7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg deleted file mode 100755 index 5a78b467..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dash-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg deleted file mode 100755 index 925e9007..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/duplicate-row-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg deleted file mode 100755 index c37b9aa7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/dynamic-mode-symbolic.svg +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg deleted file mode 100755 index f4115ada..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/edit-row-symbolic.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg deleted file mode 100755 index fa045a8b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/heart-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg deleted file mode 100755 index 45e703e4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/other-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg deleted file mode 100755 index 445f6621..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/overview-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg deleted file mode 100755 index d451b238..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/pipelines-symbolic.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg deleted file mode 100755 index a8da14f5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/remove-row-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg deleted file mode 100755 index e443de4f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/reset-symbolic.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg deleted file mode 100755 index e6d2d9e7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-row-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg deleted file mode 100755 index cad2da87..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/select-window-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg deleted file mode 100755 index 5b0eb20c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/icons/hicolor/scalable/actions/static-mode-symbolic.svg +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 9228b72c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 782420bc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 29960eb1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 2643e110..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 5f80e8bf..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index a03611b9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 9f247a26..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index abbac826..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/da/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 3639245c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index fc3ca9ba..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index a6740d8e..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 28aaedff..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index abb4ac00..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 557587b3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index f181edbc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 19693b62..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index d6a7c1fc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 8b359313..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ja/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 8c7b5101..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 1a1f9d53..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 2436b7ce..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 08487c2f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index c872ad07..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 0be2b8e1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 32f9459c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 42c4994a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index fd6301c5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 71a83aa5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 42423db2..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 9d81936c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 992144ed..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 39069b5a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 51037f3b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 8eae7c20..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index db2de664..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo deleted file mode 100755 index 4c215685..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/metadata.json deleted file mode 100755 index b9897db5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/metadata.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Adds a blur look to different parts of the GNOME Shell, including the top panel, dash and overview.\n\nYou can support my work by sponsoring me on:\n- github: https://github.com/sponsors/aunetx\n- ko-fi: https://ko-fi.com/aunetx\n\nNote: if the extension shows an error after updating, please make sure to restart your session to see if it persists. This is due to a bug in gnome shell, which I can't fix by myself.", - "donations": { - "github": "aunetx", - "kofi": "aunetx" - }, - "gettext-domain": "blur-my-shell@aunetx", - "name": "Blur my Shell", - "original-authors": [ - "me@aunetx.dev" - ], - "session-modes": [ - "unlock-dialog", - "user" - ], - "settings-schema": "org.gnome.shell.extensions.blur-my-shell", - "shell-version": [ - "46" - ], - "url": "https://github.com/aunetx/blur-my-shell", - "uuid": "blur-my-shell@aunetx", - "version": 61 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/applications.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/applications.js deleted file mode 100755 index 620d59e9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/applications.js +++ /dev/null @@ -1,186 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - -import { ApplicationRow } from './applications_management/application_row.js'; - - -const make_array = prefs_group => { - let list_box = prefs_group - .get_first_child() - .get_last_child() - .get_first_child(); - - let elements = []; - let i = 0; - let element = list_box.get_row_at_index(i); - while (element) { - elements.push(element); - i++; - element = list_box.get_row_at_index(i); - } - - return elements; -}; - - -export const Applications = GObject.registerClass({ - GTypeName: 'Applications', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/applications.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'blur', - 'sigma', - 'brightness', - 'opacity', - 'dynamic_opacity', - 'blur_on_overview', - 'enable_all', - 'whitelist', - 'add_window_whitelist', - 'blacklist', - 'add_window_blacklist' - ], -}, class Applications extends Adw.PreferencesPage { - constructor(preferences, preferences_window) { - super({}); - this._preferences_window = preferences_window; - - this.preferences = preferences; - - this.preferences.applications.settings.bind( - 'blur', this._blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'opacity', this._opacity, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'dynamic-opacity', this._dynamic_opacity, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'blur-on-overview', this._blur_on_overview, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'enable-all', this._enable_all, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'sigma', this._sigma, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.applications.settings.bind( - 'brightness', this._brightness, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - - // connect 'enable all' button to whitelist/blacklist visibility - this._enable_all.bind_property( - 'active', this._whitelist, 'visible', - GObject.BindingFlags.INVERT_BOOLEAN - ); - this._enable_all.bind_property( - 'active', this._blacklist, 'visible', - GObject.BindingFlags.DEFAULT - ); - - // make sure that blacklist / whitelist is correctly hidden - if (this._enable_all.active) - this._whitelist.visible = false; - this._blacklist.visible = !this._whitelist.visible; - - // listen to app row addition - this._add_window_whitelist.connect('clicked', - () => this.add_to_whitelist() - ); - this._add_window_blacklist.connect('clicked', - () => this.add_to_blacklist() - ); - - // add initial applications - this.add_widgets_from_lists(); - - this.preferences.connect('reset', () => { - this.remove_all_widgets(); - this.add_widgets_from_lists(); - }); - } - - // A way to retriew the whitelist widgets. - get _whitelist_elements() { - return make_array(this._whitelist); - } - - // A way to retriew the blacklist widgets. - get _blacklist_elements() { - return make_array(this._blacklist); - } - - add_widgets_from_lists() { - this.preferences.applications.WHITELIST.forEach( - app_name => this.add_to_whitelist(app_name) - ); - - this.preferences.applications.BLACKLIST.forEach( - app_name => this.add_to_blacklist(app_name) - ); - - } - - close_all_expanded_rows() { - this._whitelist_elements.forEach( - element => element.set_expanded(false) - ); - this._blacklist_elements.forEach( - element => element.set_expanded(false) - ); - } - - remove_all_widgets() { - this._whitelist_elements.forEach( - element => this._whitelist.remove(element) - ); - this._blacklist_elements.forEach( - element => this._blacklist.remove(element) - ); - } - - add_to_whitelist(app_name = null) { - let window_row = new ApplicationRow('whitelist', this, app_name); - this._whitelist.add(window_row); - } - - add_to_blacklist(app_name = null) { - let window_row = new ApplicationRow('blacklist', this, app_name); - this._blacklist.add(window_row); - } - - update_whitelist_titles() { - let titles = this._whitelist_elements - .map(element => element._window_class.buffer.text) - .filter(title => title != ""); - - this.preferences.applications.WHITELIST = titles; - } - - update_blacklist_titles() { - let titles = this._blacklist_elements - .map(element => element._window_class.buffer.text) - .filter(title => title != ""); - - this.preferences.applications.BLACKLIST = titles; - } - - remove_from_whitelist(widget) { - this._whitelist.remove(widget); - this.update_whitelist_titles(); - } - - remove_from_blacklist(widget) { - this._blacklist.remove(widget); - this.update_blacklist_titles(); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/applications_management/application_row.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/applications_management/application_row.js deleted file mode 100755 index 4af3bf87..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/applications_management/application_row.js +++ /dev/null @@ -1,112 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; - -import { pick, on_picking, on_picked } from '../../dbus/client.js'; - - -export const ApplicationRow = GObject.registerClass({ - GTypeName: 'ApplicationRow', - Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/application-row.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'window_picker', - 'window_class', - 'picking_failure_toast', - 'window_not_found_toast' - ], -}, class ApplicationRow extends Adw.ExpanderRow { - constructor(list, app_page, app_name) { - super({}); - this._list = list; - this._app_page = app_page; - - // add a 'remove' button before the text - let action_row = this.child.get_first_child().get_first_child(); - let remove_button = new Gtk.Button({ - 'icon-name': 'remove-row-symbolic', - 'width-request': 38, - 'height-request': 38, - 'margin-top': 6, - 'margin-bottom': 6, - }); - remove_button.add_css_class('circular'); - remove_button.add_css_class('flat'); - action_row.add_prefix(remove_button); - - // connect the button to the whitelist / blacklist removal - remove_button.connect('clicked', () => this._remove_row()); - - // bind row title to text buffer - this._window_class.buffer.bind_property( - 'text', this, 'title', - Gio.SettingsBindFlags.BIDIRECTIONNAL - ); - - // set application name if it exists, or open the revealer and pick one - if (app_name) - this._window_class.buffer.text = app_name; - else { - app_page.close_all_expanded_rows(); - this.set_expanded(true); - this._do_pick_window(true); - } - - // pick a window when the picker button is clicked - this._window_picker.connect('clicked', () => this._do_pick_window()); - - // update list on text buffer change - this._window_class.connect('changed', - () => this._update_rows_titles() - ); - } - - _remove_row() { - this._app_page["remove_from_" + this._list](this); - } - - _update_rows_titles() { - this._app_page["update_" + this._list + "_titles"](this); - } - - _do_pick_window(remove_if_failed = false) { - // a mechanism to know if the extension is listening correcly - let has_responded = false; - let should_take_answer = true; - setTimeout(() => { - if (!has_responded) { - // show toast about failure - this._app_page._preferences_window.add_toast( - this._picking_failure_toast - ); - - // prevent title from changing with later picks - should_take_answer = false; - - // remove row if asked - if (remove_if_failed) - this._remove_row(); - } - }, 250); - - on_picking(() => - has_responded = true - ); - - on_picked(wm_class => { - if (should_take_answer) { - if (wm_class == 'window-not-found') { - console.warn("Can't pick window from here"); - this._app_page._preferences_window.add_toast( - this._window_not_found_toast - ); - return; - } - this._window_class.buffer.text = wm_class; - } - }); - - pick(); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/dash.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/dash.js deleted file mode 100755 index aae37685..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/dash.js +++ /dev/null @@ -1,81 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Dash = GObject.registerClass({ - GTypeName: 'Dash', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/dash.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'blur', - 'pipeline_choose_row', - 'mode_static', - 'mode_dynamic', - 'sigma_row', - 'sigma', - 'brightness_row', - 'brightness', - 'override_background', - 'style_dash_to_dock', - 'unblur_in_overview' - ], -}, class Dash extends Adw.PreferencesPage { - constructor(preferences, pipelines_manager, pipelines_page) { - super({}); - - this.preferences = preferences; - this.pipelines_manager = pipelines_manager; - this.pipelines_page = pipelines_page; - - this.preferences.dash_to_dock.settings.bind( - 'blur', this._blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._pipeline_choose_row.initialize( - this.preferences.dash_to_dock, this.pipelines_manager, this.pipelines_page - ); - - this.change_blur_mode(this.preferences.dash_to_dock.STATIC_BLUR, true); - - this._mode_static.connect('toggled', - () => this.preferences.dash_to_dock.STATIC_BLUR = this._mode_static.active - ); - this.preferences.dash_to_dock.STATIC_BLUR_changed( - () => this.change_blur_mode(this.preferences.dash_to_dock.STATIC_BLUR, false) - ); - - this.preferences.dash_to_dock.settings.bind( - 'sigma', this._sigma, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.dash_to_dock.settings.bind( - 'brightness', this._brightness, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.dash_to_dock.settings.bind( - 'override-background', - this._override_background, 'enable-expansion', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.dash_to_dock.settings.bind( - 'style-dash-to-dock', this._style_dash_to_dock, 'selected', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.dash_to_dock.settings.bind( - 'unblur-in-overview', this._unblur_in_overview, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - } - - change_blur_mode(is_static_blur, first_run) { - this._mode_static.set_active(is_static_blur); - if (first_run) - this._mode_dynamic.set_active(!is_static_blur); - - this._pipeline_choose_row.set_visible(is_static_blur); - this._sigma_row.set_visible(!is_static_blur); - this._brightness_row.set_visible(!is_static_blur); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/menu.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/menu.js deleted file mode 100755 index 899fdcfc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/menu.js +++ /dev/null @@ -1,68 +0,0 @@ -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - - -export function addMenu(window) { - const builder = new Gtk.Builder(); - - // add a dummy page and remove it immediately, to access headerbar - builder.add_from_file(GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, '../ui/menu.ui', GLib.UriFlags.NONE))[0]); - let menu_util = builder.get_object('menu_util'); - window.add(menu_util); - try { - addMenuToHeader(window, builder); - } catch (error) { - // could not add menu... not so bad - } - window.remove(menu_util); -} - -function addMenuToHeader(window, builder) { - // a little hack to get to the headerbar - const page = builder.get_object('menu_util'); - const pages_stack = page.get_parent(); // AdwViewStack - const content_stack = pages_stack.get_parent().get_parent(); // GtkStack - const preferences = content_stack.get_parent(); // GtkBox - const headerbar = preferences.get_first_child().get_next_sibling() - .get_first_child().get_first_child().get_first_child(); // AdwHeaderBar - headerbar.pack_start(builder.get_object('info_menu')); - - // setup menu actions - const actionGroup = new Gio.SimpleActionGroup(); - window.insert_action_group('prefs', actionGroup); - - // a list of actions with their associated link - const actions = [ - { - name: 'open-bug-report', - link: 'https://github.com/aunetx/blur-my-shell/issues' - }, - { - name: 'open-readme', - link: 'https://github.com/aunetx/blur-my-shell' - }, - { - name: 'open-license', - link: 'https://github.com/aunetx/blur-my-shell/blob/master/LICENSE' - }, - { - name: 'donate-github', - link: 'https://github.com/sponsors/aunetx' - }, - { - name: 'donate-kofi', - link: 'https://ko-fi.com/aunetx' - }, - ]; - - actions.forEach(action => { - let act = new Gio.SimpleAction({ name: action.name }); - act.connect( - 'activate', - () => Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME) - ); - actionGroup.add_action(act); - }); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/other.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/other.js deleted file mode 100755 index b1b8f669..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/other.js +++ /dev/null @@ -1,75 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Other = GObject.registerClass({ - GTypeName: 'Other', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/other.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'lockscreen_blur', - 'lockscreen_pipeline_choose_row', - - 'screenshot_blur', - 'screenshot_pipeline_choose_row', - - 'window_list_blur', - 'window_list_sigma', - 'window_list_brightness', - - 'hack_level', - 'debug', - 'reset' - ], -}, class Overview extends Adw.PreferencesPage { - constructor(preferences, pipelines_manager, pipelines_page) { - super({}); - - this.preferences = preferences; - this.pipelines_manager = pipelines_manager; - this.pipelines_page = pipelines_page; - - this.preferences.lockscreen.settings.bind( - 'blur', this._lockscreen_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._lockscreen_pipeline_choose_row.initialize( - this.preferences.lockscreen, this.pipelines_manager, this.pipelines_page - ); - - this.preferences.screenshot.settings.bind( - 'blur', this._screenshot_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._screenshot_pipeline_choose_row.initialize( - this.preferences.screenshot, this.pipelines_manager, this.pipelines_page - ); - - this.preferences.window_list.settings.bind( - 'blur', this._window_list_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.window_list.settings.bind( - 'sigma', this._window_list_sigma, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.window_list.settings.bind( - 'brightness', this._window_list_brightness, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - - this.preferences.settings.bind( - 'hacks-level', this._hack_level, 'selected', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.settings.bind( - 'debug', this._debug, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._reset.connect('clicked', () => this.preferences.reset()); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/overview.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/overview.js deleted file mode 100755 index f6fe592a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/overview.js +++ /dev/null @@ -1,59 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Overview = GObject.registerClass({ - GTypeName: 'Overview', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/overview.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'overview_blur', - 'pipeline_choose_row', - 'overview_style_components', - - 'appfolder_blur', - 'appfolder_sigma', - 'appfolder_brightness', - 'appfolder_style_dialogs' - ], -}, class Overview extends Adw.PreferencesPage { - constructor(preferences, pipelines_manager, pipelines_page) { - super({}); - - this.preferences = preferences; - this.pipelines_manager = pipelines_manager; - this.pipelines_page = pipelines_page; - - this.preferences.overview.settings.bind( - 'blur', this._overview_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._pipeline_choose_row.initialize( - this.preferences.overview, this.pipelines_manager, this.pipelines_page - ); - - this.preferences.overview.settings.bind( - 'style-components', this._overview_style_components, 'selected', - Gio.SettingsBindFlags.DEFAULT - ); - - this.preferences.appfolder.settings.bind( - 'blur', this._appfolder_blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.appfolder.settings.bind( - 'sigma', this._appfolder_sigma, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.appfolder.settings.bind( - 'brightness', this._appfolder_brightness, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.appfolder.settings.bind( - 'style-dialogs', this._appfolder_style_dialogs, 'selected', - Gio.SettingsBindFlags.DEFAULT - ); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/panel.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/panel.js deleted file mode 100755 index c49f3239..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/panel.js +++ /dev/null @@ -1,102 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; - - -export const Panel = GObject.registerClass({ - GTypeName: 'Panel', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/panel.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'blur', - 'pipeline_choose_row', - 'mode_static', - 'mode_dynamic', - 'sigma_row', - 'sigma', - 'brightness_row', - 'brightness', - 'unblur_in_overview', - 'force_light_text', - 'override_background', - 'style_panel', - 'override_background_dynamically', - 'hidetopbar_compatibility', - 'dtp_blur_original_panel' - ], -}, class Panel extends Adw.PreferencesPage { - constructor(preferences, pipelines_manager, pipelines_page) { - super({}); - - this.preferences = preferences; - this.pipelines_manager = pipelines_manager; - this.pipelines_page = pipelines_page; - - this.preferences.panel.settings.bind( - 'blur', this._blur, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - - this._pipeline_choose_row.initialize( - this.preferences.panel, this.pipelines_manager, this.pipelines_page - ); - - this.change_blur_mode(this.preferences.panel.STATIC_BLUR, true); - - this._mode_static.connect('toggled', - () => this.preferences.panel.STATIC_BLUR = this._mode_static.active - ); - this.preferences.panel.STATIC_BLUR_changed( - () => this.change_blur_mode(this.preferences.panel.STATIC_BLUR, false) - ); - - this.preferences.panel.settings.bind( - 'sigma', this._sigma, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'brightness', this._brightness, 'value', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'unblur-in-overview', this._unblur_in_overview, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'force-light-text', this._force_light_text, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'override-background', - this._override_background, 'enable-expansion', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'style-panel', this._style_panel, 'selected', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.panel.settings.bind( - 'override-background-dynamically', - this._override_background_dynamically, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.hidetopbar.settings.bind( - 'compatibility', this._hidetopbar_compatibility, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this.preferences.dash_to_panel.settings.bind( - 'blur-original-panel', this._dtp_blur_original_panel, 'active', - Gio.SettingsBindFlags.DEFAULT - ); - } - - change_blur_mode(is_static_blur, first_run) { - this._mode_static.set_active(is_static_blur); - if (first_run) - this._mode_dynamic.set_active(!is_static_blur); - - this._pipeline_choose_row.set_visible(is_static_blur); - this._sigma_row.set_visible(!is_static_blur); - this._brightness_row.set_visible(!is_static_blur); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines.js deleted file mode 100755 index 158ea9ae..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines.js +++ /dev/null @@ -1,98 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { PipelineGroup } from './pipelines_management/pipeline_group.js'; -import { EffectsDialog } from './pipelines_management/effects_dialog.js'; - - -export const Pipelines = GObject.registerClass({ - GTypeName: 'Pipelines', - Template: GLib.uri_resolve_relative(import.meta.url, '../ui/pipelines.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'add_pipeline' - ], -}, class Pipelines extends Adw.PreferencesPage { - constructor(preferences, pipelines_manager, window) { - super({}); - - this.preferences = preferences; - this.pipelines_manager = pipelines_manager; - this.window = window; - - this.pipelines_map = new Map; - - for (let pipeline_id in this.pipelines_manager.pipelines) - this.add_pipeline(pipeline_id, false); - - this.preferences.connect('reset', _ => { - this.pipelines_map.forEach((_infos, pid) => this.remove_pipeline(pid)); - for (let pipeline_id in this.pipelines_manager.pipelines) - this.add_pipeline(pipeline_id, false); - }); - - this._add_pipeline.connect( - "clicked", - () => this.pipelines_manager.create_pipeline(_("New pipeline")) - ); - - this.pipelines_manager.connect( - "pipeline-created", - (_obj, id, _pipeline) => this.add_pipeline(id, true) - ); - } - - add_pipeline(pipeline_id, scroll_to_bottom) { - let pipeline = this.pipelines_manager.pipelines[pipeline_id]; - let pipeline_group = new PipelineGroup( - this.pipelines_manager, pipeline_id, pipeline, this - ); - - let pipeline_destroyed_id = this.pipelines_manager.connect( - pipeline_id + "::pipeline-destroyed", - () => this.remove_pipeline(pipeline_id) - ); - - let pipeline_renamed_id = this.pipelines_manager.connect( - pipeline_id + "::pipeline-renamed", - (_obj, name) => this.rename_pipeline(pipeline_id, name) - ); - - this.pipelines_map.set(pipeline_id, { - pipeline_group, pipeline_destroyed_id, pipeline_renamed_id - }); - - this.add(pipeline_group); - - // scroll to the bottom of the page - if (scroll_to_bottom) { - this.window.set_visible_page(this); - setTimeout(() => { - const scroll_adjustment = this.get_first_child().get_vadjustment(); - scroll_adjustment.value = scroll_adjustment.get_upper(); - }, 10); - pipeline_group._title.grab_focus(); - } - } - - remove_pipeline(pipeline_id) { - let pipeline_infos = this.pipelines_map.get(pipeline_id); - if (pipeline_infos) { - this.pipelines_manager.disconnect(pipeline_infos.pipeline_destroyed_id); - this.remove(pipeline_infos.pipeline_group); - this.pipelines_map.delete(pipeline_id); - } - } - - rename_pipeline(pipeline_id, name) { - let pipeline_infos = this.pipelines_map.get(pipeline_id); - if (pipeline_infos) - pipeline_infos.pipeline_group.set_title(name.length > 0 ? name : " "); - } - - open_effects_dialog(pipeline_id) { - let dialog = new EffectsDialog(this.pipelines_manager, pipeline_id); - dialog.present(this.window); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js deleted file mode 100755 index 435cace5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/effect_row.js +++ /dev/null @@ -1,209 +0,0 @@ -import Adw from 'gi://Adw'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { get_supported_effects } from '../../effects/effects.js'; - - -export const EffectRow = GObject.registerClass({ - GTypeName: 'EffectRow', - InternalChildren: [], -}, class EffectRow extends Adw.ExpanderRow { - constructor(effect, effects_dialog) { - super({}); - - this.SUPPORTED_EFFECTS = get_supported_effects(_); - - this.effect = effect; - this.effects_dialog = effects_dialog; - this.pipeline_id = effects_dialog.pipeline_id; - this.pipelines_manager = effects_dialog.pipelines_manager; - - if (effect.type in this.SUPPORTED_EFFECTS) { - this.set_title(this.SUPPORTED_EFFECTS[effect.type].name); - this.set_subtitle(this.SUPPORTED_EFFECTS[effect.type].description); - this.populate_options(); - } - else { - this._warn(`could not assign effect ${effect.type} to its correct name`); - this.set_title(effect.type); - } - - let prefix_bin = new Gtk.Box({ - spacing: 6 - }); - this.add_prefix(prefix_bin); - - let move_bin = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - 'width-request': 38, - 'height-request': 38, - 'margin-top': 6, - 'margin-bottom': 6 - }); - prefix_bin.append(move_bin); - move_bin.add_css_class('linked'); - - this._move_up_button = new Gtk.Button({ - 'icon-name': 'go-up-symbolic', - 'width-request': 38, - 'height-request': 19 - }); - this._move_down_button = new Gtk.Button({ - 'icon-name': 'go-down-symbolic', - 'width-request': 38, - 'height-request': 19 - }); - this._move_up_button.add_css_class('flat'); - this._move_down_button.add_css_class('flat'); - move_bin.append(this._move_up_button); - move_bin.append(this._move_down_button); - - this._move_up_button.connect('clicked', () => effects_dialog.move_row_by(this, -1)); - this._move_down_button.connect('clicked', () => effects_dialog.move_row_by(this, +1)); - - let remove_button = new Gtk.Button({ - 'icon-name': 'remove-row-symbolic', - 'width-request': 38, - 'height-request': 38, - 'margin-top': 6, - 'margin-bottom': 6, - 'valign': Gtk.Align.CENTER - }); - prefix_bin.append(remove_button); - remove_button.add_css_class('destructive-action'); - - remove_button.connect('clicked', () => effects_dialog.remove_row(this)); - } - - populate_options() { - const editable_params = this.SUPPORTED_EFFECTS[this.effect.type].editable_params; - for (const param_key in editable_params) { - let param = editable_params[param_key]; - let row; - switch (param.type) { - case "integer": - row = new Adw.SpinRow({ - adjustment: new Gtk.Adjustment({ - lower: param.min, - upper: param.max, - step_increment: param.increment - }) - }); - row.adjustment.set_value(this.get_effect_param(param_key)); - row.adjustment.connect( - 'value-changed', () => this.set_effect_param(param_key, row.adjustment.value) - ); - break; - - case "float": - row = new Adw.ActionRow; - let scale = new Gtk.Scale({ - valign: Gtk.Align.CENTER, - hexpand: true, - width_request: 200, - draw_value: true, - value_pos: Gtk.PositionType.RIGHT, - digits: param.digits, - adjustment: new Gtk.Adjustment({ - lower: param.min, - upper: param.max, - step_increment: param.increment, - page_increment: param.big_increment - }) - }); - // TODO check if it's a good idea to set the default parameter, as the "good" - // value really change depending on the user wallpaper... if so, do for dynamic - // blur too - scale.add_mark( - this.get_default_effect_param(param_key), Gtk.PositionType.BOTTOM, null - ); - row.add_suffix(scale); - scale.adjustment.set_value(this.get_effect_param(param_key)); - scale.adjustment.connect( - 'value-changed', () => this.set_effect_param(param_key, scale.adjustment.value) - ); - break; - - case "boolean": - row = new Adw.SwitchRow; - row.set_active(this.get_effect_param(param_key)); - row.connect( - 'notify::active', () => this.set_effect_param(param_key, row.active) - ); - break; - - case "rgba": - row = new Adw.ActionRow; - let color_button = new Gtk.ColorButton({ - valign: Gtk.Align.CENTER, - width_request: 75, - height_request: 45, - show_editor: true, - use_alpha: true - }); - row.add_suffix(color_button); - // set original color - let c = color_button.get_rgba().copy(); - [c.red, c.green, c.blue, c.alpha] = this.get_effect_param(param_key); - color_button.set_rgba(c); - // update on on 'color-set' - color_button.connect( - 'color-set', () => { - let c = color_button.get_rgba(); - this.set_effect_param(param_key, [c.red, c.green, c.blue, c.alpha]); - } - ); - break; - - default: - row = new Adw.ActionRow; - break; - } - row.set_title(param.name); - row.set_subtitle(param.description); - this.add_row(row); - } - } - - get_effect_param(key) { - let effects = this.pipelines_manager.pipelines[this.pipeline_id].effects; - const gsettings_effect = effects.find(e => e.id == this.effect.id); - - if ('params' in gsettings_effect && key in gsettings_effect.params) - return gsettings_effect.params[key]; - else - return this.get_default_effect_param(key); - } - - get_default_effect_param(key) { - return this.SUPPORTED_EFFECTS[this.effect.type].class.default_params[key]; - } - - set_effect_param(key, value) { - // we must pay attention not to change the effects in the pipelines manager before updating - // it in gsettings, else it won't be updated (or every effect will be) - let effects = this.pipelines_manager.pipelines[this.pipeline_id].effects; - const effect_index = effects.findIndex(e => e.id == this.effect.id); - - if (effect_index >= 0) { - effects[effect_index] = { - ...this.effect, params: { ...this.effect.params } - }; - effects[effect_index].params[key] = value; - this.effect = effects[effect_index]; - } - else - this._warn(`effect not found when setting key ${key}`); - - this.pipelines_manager.update_pipeline_effects(this.pipeline_id, effects, false); - } - - _warn(str) { - console.warn( - `[Blur my Shell > effect row] pipeline '${this.pipeline_id}',` - + ` effect '${this.effect.id}': ${str}` - ); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js deleted file mode 100755 index 35ac91e3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/effects_dialog.js +++ /dev/null @@ -1,150 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { EffectRow } from './effect_row.js'; -import { get_effects_groups, get_supported_effects } from '../../effects/effects.js'; - -export const EffectsDialog = GObject.registerClass({ - GTypeName: 'EffectsDialog', - Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/effects-dialog.ui', GLib.UriFlags.NONE), - InternalChildren: [ - "add_effect", - "effects_list" - ], -}, class EffectsDialog extends Adw.PreferencesDialog { - constructor(pipelines_manager, pipeline_id) { - super({}); - - this.EFFECTS_GROUPS = get_effects_groups(_); - this.SUPPORTED_EFFECTS = get_supported_effects(_); - - this.pipelines_manager = pipelines_manager; - this.pipeline_id = pipeline_id; - - let pipeline = pipelines_manager.pipelines[pipeline_id]; - - this.set_title(pipeline.name.length > 0 ? _(`Effects for "${pipeline.name}"`) : _("Effects")); - - pipeline.effects.forEach(effect => { - const effect_row = new EffectRow(effect, this); - this._effects_list.add(effect_row); - this.update_rows_insensitive_mover(effect_row); - }); - - this.build_effects_chooser(); - this._add_effect.connect('clicked', () => this.effects_chooser_dialog.present(this)); - } - - build_effects_chooser() { - this.effects_chooser_dialog = new Adw.Dialog({ - presentation_mode: Adw.DialogPresentationMode.BOTTOM_SHEET, - content_width: 450 - }); - - let page = new Adw.PreferencesPage; - this.effects_chooser_dialog.set_child(page); - - for (const effects_group in this.EFFECTS_GROUPS) { - const group_infos = this.EFFECTS_GROUPS[effects_group]; - - let group = new Adw.PreferencesGroup({ - title: group_infos.name - }); - page.add(group); - - for (const effect_type of group_infos.contains) { - if (!(effect_type in this.SUPPORTED_EFFECTS)) - continue; - - let action_row = new Adw.ActionRow({ - title: this.SUPPORTED_EFFECTS[effect_type].name, - subtitle: this.SUPPORTED_EFFECTS[effect_type].description - }); - let select_button = new Gtk.Button({ - 'icon-name': 'select-row-symbolic', - 'width-request': 38, - 'height-request': 38, - 'margin-top': 6, - 'margin-bottom': 6 - }); - group.add(action_row); - - select_button.add_css_class('flat'); - action_row.add_suffix(select_button); - action_row.set_activatable_widget(select_button); - select_button.connect('clicked', () => { - this.append_effect(effect_type); - this.effects_chooser_dialog.close(); - }); - } - } - } - - append_effect(effect_type) { - const effect = { - type: effect_type, id: "effect_" + ("" + Math.random()).slice(2, 16) - }; - this.pipelines_manager.update_pipeline_effects( - this.pipeline_id, - [...this.pipelines_manager.pipelines[this.pipeline_id].effects, effect] - ); - - const effect_row = new EffectRow(effect, this); - this._effects_list.add(effect_row); - this.move_row_by(effect_row, 0); - this.update_rows_insensitive_mover(effect_row); - } - - move_row_by(row, number) { - const effects = this.pipelines_manager.pipelines[this.pipeline_id].effects; - const effect_index = effects.findIndex(e => e.id == row.effect.id); - - if (effect_index >= 0) { - effects.splice(effect_index, 1); - effects.splice(effect_index + number, 0, row.effect); - - const listbox = row.get_parent(); - listbox.set_sort_func((row_a, row_b) => { - const id_a = effects.findIndex(e => e.id == row_a.effect.id); - const id_b = effects.findIndex(e => e.id == row_b.effect.id); - return id_a > id_b; - }); - - this.update_rows_insensitive_mover(row); - - this.pipelines_manager.update_pipeline_effects( - this.pipeline_id, effects - ); - } - } - - update_rows_insensitive_mover(any_row) { - if (this._insensitive_top) - this._insensitive_top.set_sensitive(true); - if (this._insensitive_bottom) - this._insensitive_bottom.set_sensitive(true); - - const listbox = any_row.get_parent(); - this._insensitive_top = listbox.get_first_child()._move_up_button; - this._insensitive_top?.set_sensitive(false); - this._insensitive_bottom = listbox.get_last_child()._move_down_button; - this._insensitive_bottom?.set_sensitive(false); - } - - remove_row(row) { - const effects = this.pipelines_manager.pipelines[this.pipeline_id].effects; - const effect_index = effects.findIndex(e => e.id == row.effect.id); - - if (effect_index >= 0) { - effects.splice(effect_index, 1); - this.pipelines_manager.update_pipeline_effects( - this.pipeline_id, effects - ); - } - - this._effects_list.remove(row); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js deleted file mode 100755 index e0c51658..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_choose_row.js +++ /dev/null @@ -1,106 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - - -export const PipelineChooseRow = GObject.registerClass({ - GTypeName: 'PipelineChooseRow', - Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/pipeline-choose-row.ui', GLib.UriFlags.NONE), - InternalChildren: [ - 'pipeline_choose', - 'pipeline_model', - 'pipeline_edit' - ], -}, class PipelineChooseRow extends Adw.ActionRow { - initialize(preferences, pipelines_manager, pipelines_page) { - this.preferences = preferences; - this.pipelines_manager = pipelines_manager; - this.pipelines_page = pipelines_page; - - this.create_pipelines_list(); - - // display the correct pipeline name in the drop-down instead of their ids - const closure_func = string_object => { - const pipeline_id = string_object.get_string(); - if (pipeline_id == 'create_new') - return _("Create new pipeline"); - if (pipeline_id in this.pipelines_manager.pipelines) - return this.pipelines_manager.pipelines[pipeline_id].name; - else - return ""; - }; - - const expression = new Gtk.ClosureExpression(GObject.TYPE_STRING, closure_func, []); - this._pipeline_choose.expression = expression; - - // TODO fix the expression not being re-evaluated other than by setting it again - this.pipelines_manager.connect( - 'pipeline-names-changed', - () => this._pipeline_choose.expression = new Gtk.ClosureExpression( - GObject.TYPE_STRING, closure_func, [] - ) - ); - - this.preferences.PIPELINE_changed(() => this.on_settings_pipeline_changed()); - - this.pipelines_manager.connect('pipeline-list-changed', () => this.create_pipelines_list()); - - this._pipeline_choose.connect('notify::selected', () => this.on_selected_pipeline_changed()); - - this._pipeline_edit.connect( - 'clicked', - () => this.pipelines_page.open_effects_dialog(this.preferences.PIPELINE) - ); - } - - on_selected_pipeline_changed() { - if (!this._pipeline_choose.selected_item || this._is_creating_pipelines_list) - return; - - const pipeline_id = this._pipeline_choose.selected_item.get_string(); - if (pipeline_id == 'create_new') { - const id = this.pipelines_manager.create_pipeline(_("New pipeline")); - this.preferences.PIPELINE = id; - } - else - this.preferences.PIPELINE = pipeline_id; - } - - on_settings_pipeline_changed() { - for (let i = 0; i < this._pipeline_model.n_items; i++) { - const pipeline_id = this._pipeline_model.get_string(i); - // if we have more pipelines than we should have: rebuild... - // that is the case when resetting the preferences for example - if (!(pipeline_id in this.pipelines_manager)) { - this.create_pipelines_list(); - return; - } - if (pipeline_id == this.preferences.PIPELINE) - this._pipeline_choose.set_selected(i); - } - } - - create_pipelines_list() { - // prevent the pipeline selector from being updated while re-creating the list - this._is_creating_pipelines_list = true; - - // remove ancient items - this._pipeline_model.splice(0, this._pipeline_model.n_items, null); - - // add new ones - let i = 0; - for (let pipeline_id in this.pipelines_manager.pipelines) { - this._pipeline_model.append(pipeline_id); - if (pipeline_id == this.preferences.PIPELINE) - this._pipeline_choose.set_selected(i); - i++; - } - this._pipeline_model.append('create_new'); - - // now update the drop-down selector - this._is_creating_pipelines_list = false; - this.on_selected_pipeline_changed(); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js deleted file mode 100755 index 627b5760..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/preferences/pipelines_management/pipeline_group.js +++ /dev/null @@ -1,99 +0,0 @@ -import Adw from 'gi://Adw'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { get_supported_effects } from '../../effects/effects.js'; - - -export const PipelineGroup = GObject.registerClass({ - GTypeName: 'PipelineGroup', - Template: GLib.uri_resolve_relative(import.meta.url, '../../ui/pipeline-group.ui', GLib.UriFlags.NONE), - InternalChildren: [ - "title", - "effects_description_row", - "manage_effects" - ], -}, class PipelineGroup extends Adw.PreferencesGroup { - constructor(pipelines_manager, pipeline_id, pipeline, pipelines_page) { - super({}); - - this.SUPPORTED_EFFECTS = get_supported_effects(_); - - this._pipelines_manager = pipelines_manager; - this._pipelines_page = pipelines_page; - this._pipeline_id = pipeline_id; - - // set the description - this.set_description(_(`Pipeline id: "${pipeline_id}"`)); - - // set the title and connect it to the text entry - this.set_title(pipeline.name.length > 0 ? pipeline.name : " "); - this._title.set_text(pipeline.name); - this._title.connect( - 'changed', - () => pipelines_manager.rename_pipeline(pipeline_id, this._title.get_text()) - ); - - // the bin containing the actions - let prefix_bin = new Gtk.Box; - prefix_bin.add_css_class('linked'); - this._title.add_prefix(prefix_bin); - - // add a 'remove' button if we are not the default pipeline - if (pipeline_id != "pipeline_default") { - let remove_button = new Gtk.Button({ - 'icon-name': 'remove-row-symbolic', - 'width-request': 38, - 'height-request': 38, - 'margin-top': 6, - 'margin-bottom': 6 - }); - remove_button.add_css_class('destructive-action'); - prefix_bin.append(remove_button); - remove_button.connect('clicked', () => pipelines_manager.delete_pipeline(pipeline_id)); - } - // add a 'duplicate' button - let duplicate_button = new Gtk.Button({ - 'icon-name': 'duplicate-row-symbolic', - 'width-request': 38, - 'height-request': 38, - 'margin-top': 6, - 'margin-bottom': 6 - }); - prefix_bin.append(duplicate_button); - duplicate_button.connect('clicked', () => pipelines_manager.duplicate_pipeline(pipeline_id)); - - this.update_effects_description_row(); - this._pipelines_manager.connect( - pipeline_id + '::pipeline-updated', - () => this.update_effects_description_row() - ); - - this._manage_effects.connect( - 'clicked', - () => pipelines_page.open_effects_dialog(pipeline_id) - ); - } - - update_effects_description_row() { - const effects = this._pipelines_manager.pipelines[this._pipeline_id].effects; - - if (effects.length == 0) - this._effects_description_row.set_title(_("No effect")); - else if (effects.length == 1) - this._effects_description_row.set_title(_("1 effect")); - else - this._effects_description_row.set_title(_(`${effects.length} effects`)); - - let subtitle = ""; - effects.forEach(effect => { - if (effect.type in this.SUPPORTED_EFFECTS) - subtitle += _(`${this.SUPPORTED_EFFECTS[effect.type].name}, `); - else - subtitle += _("Unknown effect, "); - }); - this._effects_description_row.set_subtitle(subtitle.slice(0, -2)); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/prefs.js deleted file mode 100755 index d90bdda1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/prefs.js +++ /dev/null @@ -1,51 +0,0 @@ -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; -import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { update_from_old_settings } from './conveniences/settings_updater.js'; -import { PipelinesManager } from './conveniences/pipelines_manager.js'; -import { Settings } from './conveniences/settings.js'; -import { KEYS } from './conveniences/keys.js'; - -import { addMenu } from './preferences/menu.js'; -import { Pipelines } from './preferences/pipelines.js'; -import { Panel } from './preferences/panel.js'; -import { Overview } from './preferences/overview.js'; -import { Dash } from './preferences/dash.js'; -import { Applications } from './preferences/applications.js'; -import { Other } from './preferences/other.js'; - -import './preferences/pipelines_management/pipeline_choose_row.js'; - - -export default class BlurMyShellPreferences extends ExtensionPreferences { - constructor(metadata) { - super(metadata); - - // load the icon theme - let iconPath = this.dir.get_child("icons").get_path(); - let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - iconTheme.add_search_path(iconPath); - } - - fillPreferencesWindow(window) { - addMenu(window); - - // update from old settings, very important for hacks level specifically - update_from_old_settings(this.getSettings()); - - const preferences = new Settings(KEYS, this.getSettings()); - const pipelines_manager = new PipelinesManager(preferences); - - const pipelines_page = new Pipelines(preferences, pipelines_manager, window); - - window.add(pipelines_page); - window.add(new Panel(preferences, pipelines_manager, pipelines_page)); - window.add(new Overview(preferences, pipelines_manager, pipelines_page)); - window.add(new Dash(preferences, pipelines_manager, pipelines_page)); - window.add(new Applications(preferences, window)); - window.add(new Other(preferences, pipelines_manager, pipelines_page)); - - window.search_enabled = true; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled deleted file mode 100755 index 604aaf97..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml deleted file mode 100755 index ff0349f6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/schemas/org.gnome.shell.extensions.blur-my-shell.gschema.xml +++ /dev/null @@ -1,569 +0,0 @@ - - - - - - - 1 - The version of the settings to update from. - - - - , - 'effects': <[ - <{ - 'type': <'native_static_gaussian_blur'>, - 'id': <'effect_000000000000'>, - 'params': <{ - 'radius': <30>, - 'brightness': <0.6> - }> - }> - ]> - }, - 'pipeline_default_rounded': { - 'name': <'Default rounded'>, - 'effects': <[ - <{ - 'type': <'native_static_gaussian_blur'>, - 'id': <'effect_000000000001'>, - 'params': <{ - 'radius': <30>, - 'brightness': <0.6> - }> - }>, - <{ - 'type': <'corner'>, - 'id': <'effect_000000000002'>, - 'params': <{ - 'radius': <24> - }> - }> - ]> - } - } - ]]> - A dictionnary describing the different pipelines and their effects. - - - - 30 - Global gaussian sigma to use - - - - 0.6 - Global brightness to use - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - true - Boolean, controls wether or not the color and noise effects are in use globally - - - - 1 - Level of hacks to use (from 0 to 2, 2 disabling clipped redraws entirely) - - - - false - Boolean, set to true to activate debug mode (more verbose journalctl logs) - - - - - - - - - - - - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - "pipeline_default" - String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - 1 - Enum to select the style of the components in overview (0 not styled, 1 light, 2 dark, 3 transparent) - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - 1 - Enum to select the style of the appfolder dialogs (0 not styled, 1 transparent, 2 light, 3 dark) - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - "pipeline_default" - String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - true - Boolean, whether to use a static or dynamic blur for this component - - - - true - Boolean, whether to disable blur from this component when opening the overview or not - - - - false - Boolean, whether or not to force the panel to have light text, useful when using light theme - - - - true - Boolean, whether to override the background or not - - - - 0 - Enum to select the style of the panel (0 transparent, 1 light, 2 dark, 3 contrasted) - - - - false - Boolean, whether to disable blur from this component when a window is close to the panel - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - "pipeline_default_rounded" - String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - true - Boolean, whether to use static or dynamic blur for this component - - - - true - Boolean, whether to override the background or not - - - - 0 - Enum to select the style of dash to dock (0 transparent, 1 light, 2 dark) - - - - false - Boolean, whether to disable blur from this component when opening the overview or not - - - - 12 - Radius for the corner rounding effect - - - - - - - - false - Boolean, whether to blur activate the blur for this component or not - - - - true - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 1. - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - 215 - Opacity of the window actor on top of the blur effect - - - - true - Wether or not to make the focused window opaque - - - - false - Wether or not to blur applications on the overview - - - - false - Wether or not to blur all applications by default - - - - [] - List of applications to blur - - - - ["Plank","com.desktop.ding", "Conky"] - List of applications not to blur - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - "pipeline_default" - String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - "pipeline_default" - String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - - - - - true - Boolean, whether to blur activate the blur for this component or not - - - - "pipeline_default" - String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used - - - - false - Boolean, whether to customize the blur effect sigma/brightness or use general values - - - - 30 - Gaussian sigma to use for the blur effect - - - - 0.6 - Brightness to use for the blur effect - - - - (0.,0.,0.,0.) - Color to mix with the blur effect - - - - 0. - Amount of noise to add to the blur effect - - - - 0. - Lightness of the noise added to the blur effect - - - - - - - - false - Boolean, whether to try compatibility with hidetopbar@mathieu.bidon.ca or not - - - - - - - - true - Boolean, whether to blur the original panel (if option selected) with Dash to Panel - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/stylesheet.css deleted file mode 100755 index b61e5305..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/stylesheet.css +++ /dev/null @@ -1,573 +0,0 @@ -/*** PANEL ***/ - -/* -* `.transparent-panel` -*/ -#panel.transparent-panel { - background: transparent; - transition-duration: 500ms; -} - -/* -* `.dark-panel` -*/ -#panel.dark-panel { - background-color: rgba(100, 100, 100, 0.35); - box-shadow: none; - transition-duration: 500ms; -} - -/* -* `.light-panel` -*/ -#panel.light-panel { - background-color: rgba(200, 200, 200, 0.2); - box-shadow: none; - transition-duration: 500ms; -} - -/* -* `.contrasted-panel` -*/ -#panel.contrasted-panel { - background-color: transparent; - box-shadow: none; - transition-duration: 500ms; -} - -.contrasted-panel .panel-button, -.contrasted-panel .clock, -.contrasted-panel .clock-display StIcon { - color: #ffffff; - border-radius: 14px; - border: 3px solid transparent; - background-color: rgba(0, 0, 0, 0.8); - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.03); -} - - -.contrasted-panel .clock-display StIcon { - padding: 8px; - margin: 0; -} - -.contrasted-panel .panel-button:hover, -.contrasted-panel .panel-button:hover .clock { - color: #ffffff; - background-color: rgba(0, 0, 0, 0.8); -} - -.contrasted-panel .clock-display { - background-color: transparent !important; - box-shadow: none !important; - border: none !important; -} - -.contrasted-panel .clock { - margin: 0 !important; -} - - -/*** DASH-TO-DOCK ***/ - -/* -* `.transparent-dash` -*/ -.transparent-dash .dash-background { - background-color: transparent !important; -} - -/* -* `.light-dash` -*/ -.light-dash .dash-background { - background-color: rgba(200, 200, 200, 0.2) !important; -} - -/* -* `.dark-dash` -*/ -.dark-dash .dash-background { - background-color: rgba(100, 100, 100, 0.35) !important; -} - - -/*** OVERVIEW ***/ - -/* -* Add transparency to the workspace animation (between workspaces) -*/ -.blurred-overview .workspace-animation { - background-color: transparent !important; -} - - -/* -* `.overview-components-transparent` -*/ - -.overview-components-transparent .workspace-thumbnail { - border: 1px solid rgba(100, 100, 100, 0.35); -} - -.overview-components-transparent .search-entry { - color: white; - background-color: rgba(0, 0, 0, 0); - border-color: transparent; - box-shadow: none; -} - -.overview-components-transparent .search-entry .search-entry-icon { - color: rgba(255, 255, 255, 0.65); -} - -.overview-components-transparent .overview-tile, -.overview-components-transparent .overview-icon, -.overview-components-transparent .grid-search-result, -.overview-components-transparent .list-search-result, -.overview-components-transparent .search-provider-icon, -/* prevents the extension from interfering with Just Perfection */ -.overview-components-transparent.just-perfection .search-section-content, -/* remove the rectangular background from the dash */ -.overview-components-transparent #dash .overview-tile, -.overview-components-transparent #dashtopanelScrollview .overview-tile { - background-color: transparent; -} - -.overview-components-transparent .workspace-thumbnail, -.overview-components-transparent .search-section-content, -.overview-components-transparent .overview-tile.app-folder, -.overview-components-transparent .page-navigation-arrow, -.overview-components-transparent .app-folder-dialog .icon-button, -/* this shouldn't apply to Dash to Dock */ -.overview-components-transparent StBoxLayout>StWidget>#dash>.dash-background { - background-color: rgba(0, 0, 0, 0); -} - -.overview-components-transparent .overview-tile:hover, -.overview-components-transparent .overview-tile:focus, -.overview-components-transparent .overview-tile:selected, -.overview-components-transparent .overview-tile:highlighted, -.overview-components-transparent .grid-search-result:hover, -.overview-components-transparent .grid-search-result:focus, -.overview-components-transparent .grid-search-result:selected, -.overview-components-transparent .grid-search-result:highlighted, -.overview-components-transparent .list-search-result:hover, -.overview-components-transparent .list-search-result:focus, -.overview-components-transparent .list-search-result:selected, -.overview-components-transparent .list-search-result:highlighted, -.overview-components-transparent .search-provider-icon:hover, -.overview-components-transparent .search-provider-icon:focus, -.overview-components-transparent .page-navigation-arrow:hover, -.overview-components-transparent .page-navigation-arrow:focus, -.overview-components-transparent .app-folder-dialog .icon-button:hover, -.overview-components-transparent .app-folder-dialog .icon-button:focus, -.overview-components-transparent #dash .overview-tile:hover .overview-icon, -.overview-components-transparent #dash .overview-tile:focus .overview-icon, -.overview-components-transparent #dash .show-apps:hover .overview-icon, -.overview-components-transparent #dash .show-apps:focus .overview-icon { - background-color: rgba(230, 230, 230, 0.08); -} - -.overview-components-transparent .overview-tile:active, -.overview-components-transparent .overview-tile:focus:hover, -.overview-components-transparent .overview-tile:drop, -.overview-components-transparent .overview-tile:selected:hover, -.overview-components-transparent .overview-tile:highlighted:hover, -.overview-components-transparent .grid-search-result:active, -.overview-components-transparent .grid-search-result:focus:hover, -.overview-components-transparent .grid-search-result:selected:hover, -.overview-components-transparent .grid-search-result:highlighted:hover, -.overview-components-transparent .list-search-result:active, -.overview-components-transparent .list-search-result:focus:hover, -.overview-components-transparent .list-search-result:selected:hover, -.overview-components-transparent .list-search-result:highlighted:hover, -.overview-components-transparent .search-provider-icon:active, -.overview-components-transparent .search-provider-icon:focus:hover, -.overview-components-transparent .page-navigation-arrow:active, -.overview-components-transparent .page-navigation-arrow:focus:hover, -.overview-components-transparent .app-folder-dialog .icon-button:active, -.overview-components-transparent .app-folder-dialog .icon-button:focus:hover, -.overview-components-transparent #dash .overview-tile:active .overview-icon, -.overview-components-transparent #dash .overview-tile:focus:hover .overview-icon, -.overview-components-transparent #dash .overview-tile:drop .overview-icon, -.overview-components-transparent #dash .show-apps:checked .overview-icon { - background-color: rgba(230, 230, 230, 0.12); -} - -.overview-components-transparent .overview-tile:focus:active, -.overview-components-transparent .overview-tile:selected:active, -.overview-components-transparent .overview-tile:highlighted:active, -.overview-components-transparent .grid-search-result:focus:active, -.overview-components-transparent .grid-search-result:selected:active, -.overview-components-transparent .grid-search-result:highlighted:active, -.overview-components-transparent .list-search-result:focus:active, -.overview-components-transparent .list-search-result:selected:active, -.overview-components-transparent .list-search-result:highlighted:active, -.overview-components-transparent .search-provider-icon:focus:active, -.overview-components-transparent .page-navigation-arrow:focus:active, -.overview-components-transparent .app-folder-dialog .icon-button:focus:active, -.overview-components-transparent #dash .show-apps:checked .overview-icon:hover { - background-color: rgba(230, 230, 230, 0.15); -} - - -/* -* `.overview-components-light` -*/ - -.overview-components-light .search-entry { - color: white; - background-color: rgba(200, 200, 200, 0.2); - border-color: transparent; - box-shadow: none; -} - -.overview-components-light .search-entry .search-entry-icon { - color: rgba(255, 255, 255, 0.65); -} - -.overview-components-light .overview-tile, -.overview-components-light .overview-icon, -.overview-components-light .grid-search-result, -.overview-components-light .list-search-result, -.overview-components-light .search-provider-icon, -/* prevents the extension from interfering with Just Perfection */ -.overview-components-light.just-perfection .search-section-content, -/* remove the rectangular background from the dash */ -.overview-components-light #dash .overview-tile, -.overview-components-light #dashtopanelScrollview .overview-tile { - background-color: transparent; -} - -.overview-components-light .workspace-thumbnail, -.overview-components-light .search-section-content, -.overview-components-light .overview-tile.app-folder, -.overview-components-light .page-navigation-arrow, -.overview-components-light .app-folder-dialog .icon-button, -/* this shouldn't apply to Dash to Dock */ -.overview-components-light StBoxLayout>StWidget>#dash>.dash-background { - background-color: rgba(200, 200, 200, 0.2); -} - -.overview-components-light .overview-tile:hover, -.overview-components-light .overview-tile:focus, -.overview-components-light .overview-tile:selected, -.overview-components-light .overview-tile:highlighted, -.overview-components-light .grid-search-result:hover, -.overview-components-light .grid-search-result:focus, -.overview-components-light .grid-search-result:selected, -.overview-components-light .grid-search-result:highlighted, -.overview-components-light .list-search-result:hover, -.overview-components-light .list-search-result:focus, -.overview-components-light .list-search-result:selected, -.overview-components-light .list-search-result:highlighted, -.overview-components-light .search-provider-icon:hover, -.overview-components-light .search-provider-icon:focus, -.overview-components-light .page-navigation-arrow:hover, -.overview-components-light .page-navigation-arrow:focus, -.overview-components-light .app-folder-dialog .icon-button:hover, -.overview-components-light .app-folder-dialog .icon-button:focus, -.overview-components-light #dash .overview-tile:hover .overview-icon, -.overview-components-light #dash .overview-tile:focus .overview-icon, -.overview-components-light #dash .show-apps:hover .overview-icon, -.overview-components-light #dash .show-apps:focus .overview-icon { - background-color: rgba(230, 230, 230, 0.2); -} - -.overview-components-light .overview-tile:active, -.overview-components-light .overview-tile:focus:hover, -.overview-components-light .overview-tile:drop, -.overview-components-light .overview-tile:selected:hover, -.overview-components-light .overview-tile:highlighted:hover, -.overview-components-light .grid-search-result:active, -.overview-components-light .grid-search-result:focus:hover, -.overview-components-light .grid-search-result:selected:hover, -.overview-components-light .grid-search-result:highlighted:hover, -.overview-components-light .list-search-result:active, -.overview-components-light .list-search-result:focus:hover, -.overview-components-light .list-search-result:selected:hover, -.overview-components-light .list-search-result:highlighted:hover, -.overview-components-light .search-provider-icon:active, -.overview-components-light .search-provider-icon:focus:hover, -.overview-components-light .page-navigation-arrow:active, -.overview-components-light .page-navigation-arrow:focus:hover, -.overview-components-light .app-folder-dialog .icon-button:active, -.overview-components-light .app-folder-dialog .icon-button:focus:hover, -.overview-components-light #dash .overview-tile:active .overview-icon, -.overview-components-light #dash .overview-tile:focus:hover .overview-icon, -.overview-components-light #dash .overview-tile:drop .overview-icon, -.overview-components-light #dash .show-apps:checked .overview-icon { - background-color: rgba(230, 230, 230, 0.25); -} - -.overview-components-light .overview-tile:focus:active, -.overview-components-light .overview-tile:selected:active, -.overview-components-light .overview-tile:highlighted:active, -.overview-components-light .grid-search-result:focus:active, -.overview-components-light .grid-search-result:selected:active, -.overview-components-light .grid-search-result:highlighted:active, -.overview-components-light .list-search-result:focus:active, -.overview-components-light .list-search-result:selected:active, -.overview-components-light .list-search-result:highlighted:active, -.overview-components-light .search-provider-icon:focus:active, -.overview-components-light .page-navigation-arrow:focus:active, -.overview-components-light .app-folder-dialog .icon-button:focus:active, -.overview-components-light #dash .show-apps:checked .overview-icon:hover { - background-color: rgba(230, 230, 230, 0.3); -} - - -/* -* `.overview-components-dark` -*/ - -.overview-components-dark .search-entry { - color: white; - background-color: rgba(100, 100, 100, 0.35); - border-color: transparent; - box-shadow: none; -} - -.overview-components-dark .search-entry .search-entry-icon { - color: rgba(255, 255, 255, 0.65); -} - -.overview-components-dark .overview-tile, -.overview-components-dark .overview-icon, -.overview-components-dark .grid-search-result, -.overview-components-dark .list-search-result, -.overview-components-dark .search-provider-icon, -/* prevents the extension from interfering with Just Perfection */ -.overview-components-dark.just-perfection .search-section-content, -/* remove the rectangular background from the dash */ -.overview-components-dark #dash .overview-tile, -.overview-components-dark #dashtopanelScrollview .overview-tile { - background-color: transparent; -} - -.overview-components-dark .workspace-thumbnail, -.overview-components-dark .search-section-content, -.overview-components-dark .overview-tile.app-folder, -.overview-components-dark .page-navigation-arrow, -.overview-components-dark .app-folder-dialog .icon-button, -/* this shouldn't apply to Dash to Dock */ -.overview-components-dark StBoxLayout>StWidget>#dash>.dash-background { - background-color: rgba(100, 100, 100, 0.35); -} - -.overview-components-dark .overview-tile:hover, -.overview-components-dark .overview-tile:focus, -.overview-components-dark .overview-tile:selected, -.overview-components-dark .overview-tile:highlighted, -.overview-components-dark .grid-search-result:hover, -.overview-components-dark .grid-search-result:focus, -.overview-components-dark .grid-search-result:selected, -.overview-components-dark .grid-search-result:highlighted, -.overview-components-dark .list-search-result:hover, -.overview-components-dark .list-search-result:focus, -.overview-components-dark .list-search-result:selected, -.overview-components-dark .list-search-result:highlighted, -.overview-components-dark .search-provider-icon:hover, -.overview-components-dark .search-provider-icon:focus, -.overview-components-dark .page-navigation-arrow:hover, -.overview-components-dark .page-navigation-arrow:focus, -.overview-components-dark .app-folder-dialog .icon-button:hover, -.overview-components-dark .app-folder-dialog .icon-button:focus, -.overview-components-dark #dash .overview-tile:hover .overview-icon, -.overview-components-dark #dash .overview-tile:focus .overview-icon, -.overview-components-dark #dash .show-apps:hover .overview-icon, -.overview-components-dark #dash .show-apps:focus .overview-icon { - background-color: rgba(120, 120, 120, 0.35); -} - -.overview-components-dark .overview-tile:active, -.overview-components-dark .overview-tile:focus:hover, -.overview-components-dark .overview-tile:drop, -.overview-components-dark .overview-tile:selected:hover, -.overview-components-dark .overview-tile:highlighted:hover, -.overview-components-dark .grid-search-result:active, -.overview-components-dark .grid-search-result:focus:hover, -.overview-components-dark .grid-search-result:selected:hover, -.overview-components-dark .grid-search-result:highlighted:hover, -.overview-components-dark .list-search-result:active, -.overview-components-dark .list-search-result:focus:hover, -.overview-components-dark .list-search-result:selected:hover, -.overview-components-dark .list-search-result:highlighted:hover, -.overview-components-dark .search-provider-icon:active, -.overview-components-dark .search-provider-icon:focus:hover, -.overview-components-dark .page-navigation-arrow:active, -.overview-components-dark .page-navigation-arrow:focus:hover, -.overview-components-dark .app-folder-dialog .icon-button:active, -.overview-components-dark .app-folder-dialog .icon-button:focus:hover, -.overview-components-dark #dash .overview-tile:active .overview-icon, -.overview-components-dark #dash .overview-tile:focus:hover .overview-icon, -.overview-components-dark #dash .overview-tile:drop .overview-icon, -.overview-components-dark #dash .show-apps:checked .overview-icon { - background-color: rgba(120, 120, 120, 0.4); -} - -.overview-components-dark .overview-tile:focus:active, -.overview-components-dark .overview-tile:selected:active, -.overview-components-dark .overview-tile:highlighted:active, -.overview-components-dark .grid-search-result:focus:active, -.overview-components-dark .grid-search-result:selected:active, -.overview-components-dark .grid-search-result:highlighted:active, -.overview-components-dark .list-search-result:focus:active, -.overview-components-dark .list-search-result:selected:active, -.overview-components-dark .list-search-result:highlighted:active, -.overview-components-dark .search-provider-icon:focus:active, -.overview-components-dark .page-navigation-arrow:focus:active, -.overview-components-dark .app-folder-dialog .icon-button:focus:active, -.overview-components-dark #dash .show-apps:checked .overview-icon:hover { - background-color: rgba(120, 120, 120, 0.45); -} - - -/*** APPFOLDER DIALOG ***/ - -/* -* `.appfolder-dialogs-transparent` -*/ - -.appfolder-dialogs-transparent { - background-color: rgba(0, 0, 0, 0); - border: none; - box-shadow: none; -} - -.appfolder-dialogs-transparent .folder-name-entry { - color: white; - background-color: rgba(0, 0, 0, 0); - border: 0; - box-shadow: none; -} - -/* -* `.appfolder-dialogs-light` -*/ - -.appfolder-dialogs-light { - background-color: rgba(200, 200, 200, 0.2); - border: none; - box-shadow: none; -} - -.appfolder-dialogs-light .folder-name-entry { - color: white; - background-color: rgba(200, 200, 200, 0.2); - border: 0; - box-shadow: none; -} - - -/* -* `.appfolder-dialogs-dark` -*/ - -.appfolder-dialogs-dark { - background-color: rgba(100, 100, 100, 0.35); - border: none; - box-shadow: none; -} - -.appfolder-dialogs-dark .folder-name-entry { - color: white; - background-color: rgba(100, 100, 100, 0.35); - border: 0; - box-shadow: none; -} - - -/*** PANEL LIGHT TEXT ***/ - -/* -* `.panel-light-text`, adapted from gnome-shell-light.css -*/ - -#panel.panel-light-text .panel-button, -#panel.panel-light-text .panel-button.clock-display, -#panel.panel-light-text .netSpeedLabel { - color: #f6f5f4; - box-shadow: none; -} - -#panel.panel-light-text .panel-button:active, -#panel.panel-light-text .panel-button:focus, -#panel.panel-light-text .panel-button:checked, -#panel.panel-light-text .panel-button.clock-display:active .clock, -#panel.panel-light-text .panel-button.clock-display:focus .clock, -#panel.panel-light-text .panel-button.clock-display:checked .clock { - box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.25); -} - -#panel.panel-light-text .panel-button:active:hover, -#panel.panel-light-text .panel-button:focus:hover, -#panel.panel-light-text .panel-button:checked:hover, -#panel.panel-light-text .panel-button.clock-display:active:hover, -#panel.panel-light-text .panel-button.clock-display:focus:hover, -#panel.panel-light-text .panel-button.clock-display:checked:hover, -#panel.panel-light-text .panel-button.clock-display:active .clock:hover, -#panel.panel-light-text .panel-button.clock-display:focus .clock:hover, -#panel.panel-light-text .panel-button.clock-display:checked .clock:hover { - box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.35); -} - -#panel.panel-light-text .panel-button:hover, -#panel.panel-light-text .panel-button.clock-display:hover, -#panel.panel-light-text .panel-button.clock-display:hover .clock { - box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.2); -} - -#panel.panel-light-text .panel-button#panelActivities .workspace-dot { - background-color: #f6f5f4; -} - -#panel.panel-light-text .panel-button.clock-display:active, -#panel.panel-light-text .panel-button.clock-display:focus, -#panel.panel-light-text .panel-button.clock-display:checked, -#panel.panel-light-text .panel-button.clock-display:hover { - box-shadow: none !important; -} - -#panel.panel-light-text .panel-button.screen-recording-indicator { - color: #f6f5f4; - box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.8); -} - -#panel.panel-light-text .panel-button.screen-recording-indicator:active, -#panel.panel-light-text .panel-button.screen-recording-indicator:focus, -#panel.panel-light-text .panel-button.screen-recording-indicator:checked { - box-shadow: inset 0 0 0 100px #c01c28; -} - -#panel.panel-light-text .panel-button.screen-recording-indicator:active:hover, -#panel.panel-light-text .panel-button.screen-recording-indicator:focus:hover, -#panel.panel-light-text .panel-button.screen-recording-indicator:checked:hover { - box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.95); -} - -#panel.panel-light-text .panel-button.screen-recording-indicator:hover { - box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.9); -} - -#panel.panel-light-text .panel-button.screen-sharing-indicator { - color: #282828; - box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.8); -} - -#panel.panel-light-text .panel-button.screen-sharing-indicator:active, -#panel.panel-light-text .panel-button.screen-sharing-indicator:focus, -#panel.panel-light-text .panel-button.screen-sharing-indicator:checked { - box-shadow: inset 0 0 0 100px #ff7800; -} - -#panel.panel-light-text .panel-button.screen-sharing-indicator:active:hover, -#panel.panel-light-text .panel-button.screen-sharing-indicator:focus:hover, -#panel.panel-light-text .panel-button.screen-sharing-indicator:checked:hover { - box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.95); -} - -#panel.panel-light-text .panel-button.screen-sharing-indicator:hover { - box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.9); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/application-row.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/application-row.ui deleted file mode 100755 index 2a26d145..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/application-row.ui +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - Could not pick window, make sure that the extension is enabled. - - - - Could not pick window from here, does not seem like a valid window. - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/applications.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/applications.ui deleted file mode 100755 index 91f17c13..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/applications.ui +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - 0 - 100 - 1 - - - - 0.0 - 1.0 - 0.01 - - - - 25 - 255 - 1 - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/dash.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/dash.ui deleted file mode 100755 index b08a4d1b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/dash.ui +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - 0 - 100 - 1 - - - - 0.0 - 1.0 - 0.01 - - - - - Transparent - Light - Dark - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/effects-dialog.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/effects-dialog.ui deleted file mode 100755 index 142b6056..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/effects-dialog.ui +++ /dev/null @@ -1,48 +0,0 @@ - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/menu.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/menu.ui deleted file mode 100755 index 6d2a4741..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/menu.ui +++ /dev/null @@ -1,37 +0,0 @@ - - - -
- - Project page - prefs.open-readme - - - Report a Bug - prefs.open-bug-report - - - License - prefs.open-license - - - Donate - - GitHub - prefs.donate-github - - - Ko-fi - prefs.donate-kofi - - -
-
- - - info_menu_model - heart-symbolic - - - -
\ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/other.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/other.ui deleted file mode 100755 index 1c1b3e9e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/other.ui +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - 0 - 100 - 1 - - - - 0.0 - 1.0 - 0.01 - - - - - High performances - Default - No artifact - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/overview.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/overview.ui deleted file mode 100755 index 36b91fc7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/overview.ui +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - Do not style - Light - Dark - Transparent - - - - - 0 - 100 - 1 - - - - 0.0 - 1.0 - 0.01 - - - - - - Do not style - Transparent - Light - Dark - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/panel.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/panel.ui deleted file mode 100755 index 306f4efa..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/panel.ui +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - Transparent - Light - Dark - Contrasted - - - - - 0 - 100 - 1 - - - - 0.0 - 1.0 - 0.01 - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipeline-choose-row.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipeline-choose-row.ui deleted file mode 100755 index 72b854bd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipeline-choose-row.ui +++ /dev/null @@ -1,39 +0,0 @@ - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipeline-group.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipeline-group.ui deleted file mode 100755 index 19a12bf7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipeline-group.ui +++ /dev/null @@ -1,29 +0,0 @@ - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipelines.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipelines.ui deleted file mode 100755 index 555ec0a2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/blur-my-shell@aunetx/ui/pipelines.ui +++ /dev/null @@ -1,44 +0,0 @@ - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/LICENSE b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/LICENSE deleted file mode 100755 index e72bfdda..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/extension.js deleted file mode 100755 index e62aac19..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/extension.js +++ /dev/null @@ -1,482 +0,0 @@ - -/* - * Compiz-alike-magic-lamp-effect for GNOME Shell - * - * Copyright (C) 2020 - * Mauro Pepe - * - * This file is part of the gnome-shell extension Compiz-alike-magic-lamp-effect. - * - * gnome-shell extension Compiz-alike-magic-lamp-effect is free software: you can - * redistribute it and/or modify it under the terms of the GNU - * General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * gnome-shell extension Compiz-alike-magic-lamp-effect is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gnome-shell extension Compiz-alike-magic-lamp-effect. If not, see - * . - */ -'use strict'; - -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import St from 'gi://St'; - -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import { SettingsData } from './settings_data.js'; - -const MINIMIZE_EFFECT_NAME = 'minimize-magic-lamp-effect'; -const UNMINIMIZE_EFFECT_NAME = 'unminimize-magic-lamp-effect'; - -export default class CompizMagicLampEffectExtension extends Extension { - - enable() { - this.settingsData = new SettingsData(this.getSettings()); - - // https://github.com/GNOME/gnome-shell/blob/master/js/ui/windowManager.js - - Main.wm.original_minimizeMaximizeWindow_shouldAnimateActor = Main.wm._shouldAnimateActor; - Main.wm._shouldAnimateActor = function(actor, types) { - let stack = new Error().stack; - if (stack && (stack.indexOf("_minimizeWindow") !== -1 || stack.indexOf("_unminimizeWindow") !== -1)) { - return false; - } - - return Main.wm.original_minimizeMaximizeWindow_shouldAnimateActor(actor, types); - }; - - Main.wm._shellwm.original_completed_minimize = Main.wm._shellwm.completed_minimize; - Main.wm._shellwm.completed_minimize = function(actor) { - return; - }; - - Main.wm._shellwm.original_completed_unminimize = Main.wm._shellwm.completed_unminimize; - Main.wm._shellwm.completed_unminimize = function(actor) { - return; - }; - - this.minimizeId = global.window_manager.connect("minimize", (e, actor) => { - if (Main.overview.visible) { - Main.wm._shellwm.original_completed_minimize(actor); - return; - } - - let icon = this.getIcon(actor); - - this.destroyActorEffect(actor); - - actor.add_effect_with_name(MINIMIZE_EFFECT_NAME, new MagicLampMinimizeEffect({settingsData: this.settingsData, icon: icon})); - }); - - this.unminimizeId = global.window_manager.connect("unminimize", (e, actor) => { - actor.show(); - - if (Main.overview.visible) { - Main.wm._shellwm.original_completed_unminimize(actor); - return; - } - - let icon = this.getIcon(actor); - - this.destroyActorEffect(actor); - - actor.add_effect_with_name(UNMINIMIZE_EFFECT_NAME, new MagicLampUnminimizeEffect({settingsData: this.settingsData, icon: icon})); - }); - } - - disable() { - if (this.settingsData) { - this.settingsData = null; - } - if (this.minimizeId) { - global.window_manager.disconnect(this.minimizeId); - } - if (this.minimizeId) { - global.window_manager.disconnect(this.unminimizeId); - } - - global.get_window_actors().forEach((actor) => { - this.destroyActorEffect(actor); - }); - - if (Main.wm.original_minimizeMaximizeWindow_shouldAnimateActor) { - Main.wm._shouldAnimateActor = Main.wm.original_minimizeMaximizeWindow_shouldAnimateActor; - Main.wm.original_minimizeMaximizeWindow_shouldAnimateActor = null; - } - if (Main.wm._shellwm.original_completed_minimize) { - Main.wm._shellwm.completed_minimize = Main.wm._shellwm.original_completed_minimize; - Main.wm._shellwm.original_completed_minimize = null; - } - if (Main.wm._shellwm.original_completed_unminimize) { - Main.wm._shellwm.completed_unminimize = Main.wm._shellwm.original_completed_unminimize; - Main.wm._shellwm.original_completed_unminimize = null; - } - } - - getIcon(actor) { - let [success, icon] = actor.meta_window.get_icon_geometry(); - if (success) { - return icon; - } - - let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()]; - if (monitor && Main.overview.dash) { - Main.overview.dash._redisplay(); - - let dashIcon = null; - let transformed_position = null; - let pids = null; - let pid = actor.get_meta_window() ? actor.get_meta_window().get_pid() : null; - if (pid) { - Main.overview.dash._box.get_children() - .filter(dashElement => dashElement.child && dashElement.child._delegate && dashElement.child._delegate.app) - .forEach(dashElement => { - pids = dashElement.child._delegate.app.get_pids(); - if (pids && pids.indexOf(pid) >= 0) { - transformed_position = dashElement.get_transformed_position(); - if (transformed_position && transformed_position[0]) { - dashIcon = {x: transformed_position[0], y: monitor.y + monitor.height, width: 0, height: 0}; - return; - } - } - }); - } - if (dashIcon) { - return dashIcon; - } - - return {x: monitor.x + monitor.width / 2, y: monitor.y + monitor.height, width: 0, height: 0}; - } - - return {x: 0, y: 0, width: 0, height: 0}; - } - - destroyActorEffect(actor) { - if (!actor) { - return; - } - - let minimizeEffect = actor.get_effect(MINIMIZE_EFFECT_NAME); - if (minimizeEffect) { - minimizeEffect.destroy(); - } - - let unminimizeEffect = actor.get_effect(UNMINIMIZE_EFFECT_NAME); - if (unminimizeEffect) { - unminimizeEffect.destroy(); - } - } -} - -class AbstractCommonMagicLampEffect extends Clutter.DeformEffect { - static { - GObject.registerClass(this); - } - - _init(params = {}) { - super._init(); - - this.settingsData = params.settingsData; - - this.EPSILON = 40; - - this.isMinimizeEffect = false; - this.newFrameEvent = null; - this.completedEvent = null; - - this.timerId = null; - this.msecs = 0; - - this.monitor = {x: 0, y: 0, width: 0, height: 0}; - this.iconMonitor = {x: 0, y: 0, width: 0, height: 0}; - this.window = {x: 0, y: 0, width: 0, height: 0, scale: 1}; - this.icon = params.icon; - - this.progress = 0; - this.split = 0.3; - this.k = 0; - this.j = 0; - this.expandWidth = 0; - this.fullWidth = 0; - this.expandHeight = 0; - this.fullHeight = 0; - this.width = 0; - this.height = 0; - this.x = 0; - this.y = 0; - this.offsetX = 0; - this.offsetY = 0; - this.effectX = 0; - this.effectY = 0; - this.iconPosition = null; - - this.toTheBorder = true; // true - this.maxIconSize = null; // 48 - this.alignIcon = 'center'; // 'left-top' - - this.EFFECT = this.settingsData.EFFECT.get(); //'default' - 'sine' - this.DURATION = this.settingsData.DURATION.get(); - this.X_TILES = this.settingsData.X_TILES.get(); - this.Y_TILES = this.settingsData.Y_TILES.get(); - - this.initialized = false; - } - - destroy_actor(actor) {} - - on_tick_elapsed(timer, msecs) {} - - vfunc_set_actor(actor) { - super.vfunc_set_actor(actor); - - if (!this.actor || this.initialized) { - return; - } - - this.initialized = true; - - this.monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()]; - - [this.window.x, this.window.y] = [this.actor.get_x() - this.monitor.x, this.actor.get_y() - this.monitor.y]; - [this.window.width, this.window.height] = actor.get_size(); - - if (!this.icon || (this.icon.x == 0 && this.icon.y == 0 && this.icon.width == 0 && this.icon.height == 0)) { - this.icon.x = this.monitor.x + this.monitor.width / 2; - this.icon.y = this.monitor.height + this.monitor.y; - } - - Main.layoutManager.monitors.forEach((monitor, monitorIndex) => { - let scale = 1; - if (global.display && global.display.get_monitor_scale) { - scale = global.display.get_monitor_scale(monitorIndex); - } - - if (this.icon.x >= monitor.x && this.icon.x <= monitor.x + monitor.width * scale && this.icon.y >= monitor.y && this.icon.y <= monitor.y + monitor.height * scale) { - this.iconMonitor = monitor; - } - }); - if (this.iconMonitor.x == 0 && this.iconMonitor.y == 0 && this.iconMonitor.width == 0 && this.iconMonitor.height == 0) { - this.iconMonitor = this.monitor; - // this.icon.x = this.monitor.x + this.monitor.width / 2; - // this.icon.y = this.monitor.height + this.monitor.y; - } - - [this.icon.x, this.icon.y, this.icon.width, this.icon.height] = [this.icon.x - this.monitor.x, this.icon.y - this.monitor.y, this.icon.width, this.icon.height]; - - if (this.icon.y + this.icon.height >= this.monitor.height - this.EPSILON) { - this.iconPosition = St.Side.BOTTOM; - if (this.toTheBorder) { - this.icon.y = this.iconMonitor.y + this.iconMonitor.height - this.monitor.y - this.icon.height = 0; - } - } else if (this.icon.x <= this.EPSILON) { - this.iconPosition = St.Side.LEFT; - if (this.toTheBorder) { - this.icon.x = this.iconMonitor.x - this.monitor.x; - this.icon.width = 0; - } - } else if (this.icon.x + this.icon.width >= this.monitor.width - this.EPSILON) { - this.iconPosition = St.Side.RIGHT; - if (this.toTheBorder) { - this.icon.x = this.iconMonitor.x + this.iconMonitor.width - this.monitor.x; - this.icon.width = 0; - } - } else { - this.iconPosition = St.Side.TOP; - if (this.toTheBorder) { - this.icon.y = this.iconMonitor.y - this.monitor.y; - this.icon.height = 0; - } - } - - this.set_n_tiles(this.X_TILES, this.Y_TILES); - - this.timerId = new Clutter.Timeline({ actor: this.actor, duration: this.DURATION + (this.monitor.width * this.monitor.height) / (this.window.width * this.window.height) }); - this.newFrameEvent = this.timerId.connect('new-frame', this.on_tick_elapsed.bind(this)); - this.completedEvent = this.timerId.connect('completed', this.destroy.bind(this)); - this.timerId.start(); - } - - destroy() { - if (this.timerId) { - if (this.newFrameEvent) { - this.timerId.disconnect(this.newFrameEvent); - this.newFrameEvent = null; - } - if (this.completedEvent) { - this.timerId.disconnect(this.completedEvent); - this.completedEvent = null; - } - this.timerId = null; - } - - let actor = this.get_actor(); - if (actor) { - if (this.paintEvent) { - actor.disconnect(this.paintEvent); - this.paintEvent = null; - } - actor.remove_effect(this); - - this.destroy_actor(actor); - } - } - - vfunc_deform_vertex(w, h, v) { - if (this.initialized) { - let propX = w / this.window.width; - let propY = h / this.window.height; - - if (this.iconPosition == St.Side.LEFT) { - this.width = this.window.width - this.icon.width + this.window.x * this.k; - - this.x = (this.width - this.j * this.width) * v.tx; - this.y = v.ty * this.window.height * (this.x + (this.width - this.x) * (1 - this.k)) / this.width + - v.ty * this.icon.height * (this.width - this.x) / this.width; - - this.offsetX = this.icon.width - this.window.x * this.k; - this.offsetY = (this.icon.y - this.window.y) * ((this.width - this.x) / this.width) * this.k; - - if (this.EFFECT === 'sine') { - this.effectY = Math.sin(this.x / this.width * Math.PI * 4) * this.window.height / 14 * this.k; - } else { - this.effectY = Math.sin((0.5 - (this.width - this.x) / this.width) * 2 * Math.PI) * (this.window.y + this.window.height * v.ty - (this.icon.y + this.icon.height * v.ty)) / 7 * this.k; - } - } else if (this.iconPosition == St.Side.TOP) { - this.height = this.window.height - this.icon.height + this.window.y * this.k; - - this.y = (this.height - this.j * this.height) * v.ty; - this.x = v.tx * this.window.width * (this.y + (this.height - this.y) * (1 - this.k)) / this.height + - v.tx * this.icon.width * (this.height - this.y) / this.height; - - this.offsetX = (this.icon.x - this.window.x) * ((this.height - this.y) / this.height) * this.k; - this.offsetY = this.icon.height - this.window.y * this.k; - - if (this.EFFECT === 'sine') { - this.effectX = Math.sin(this.y / this.height * Math.PI * 4) * this.window.width / 14 * this.k; - } else { - this.effectX = Math.sin((0.5 - (this.height - this.y) / this.height) * 2 * Math.PI) * (this.window.x + this.window.width * v.tx - (this.icon.x + this.icon.width * v.tx)) / 7 * this.k; - } - } else if (this.iconPosition == St.Side.RIGHT) { - this.expandWidth = (this.iconMonitor.width - this.icon.width - this.window.x - this.window.width); - this.fullWidth = (this.iconMonitor.width - this.icon.width - this.window.x) - this.expandWidth * (1 - this.k); - this.width = this.fullWidth - this.j * this.fullWidth; - - this.x = v.tx * this.width; - this.y = v.ty * (this.icon.height) + - v.ty * (this.window.height - this.icon.height) * (1 - this.j) * (1 - v.tx) + - v.ty * (this.window.height - this.icon.height) * (1 - this.k) * (v.tx); - - this.offsetY = (this.icon.y - this.window.y) * (this.x / this.fullWidth) * this.k + (this.icon.y - this.window.y) * this.j; - this.offsetX = this.iconMonitor.width - this.icon.width - this.window.x - this.width - this.expandWidth * (1 - this.k); - - if (this.EFFECT === 'sine') { - this.effectY = Math.sin((this.width - this.x) / this.fullWidth * Math.PI * 4) * this.window.height / 14 * this.k; - } else { - this.effectY = Math.sin(((this.width - this.x) / this.fullWidth) * 2 * Math.PI + Math.PI) * (this.window.y + this.window.height * v.ty - (this.icon.y + this.icon.height * v.ty)) / 7 * this.k; - } - } else if (this.iconPosition == St.Side.BOTTOM) { - this.expandHeight = (this.iconMonitor.height - this.icon.height - this.window.y - this.window.height); - this.fullHeight = (this.iconMonitor.height - this.icon.height - this.window.y) - this.expandHeight * (1 - this.k); - this.height = this.fullHeight - this.j * this.fullHeight; - - this.y = v.ty * this.height; - this.x = v.tx * (this.icon.width) + - v.tx * (this.window.width - this.icon.width) * (1 - this.j) * (1 - v.ty) + - v.tx * (this.window.width - this.icon.width) * (1 - this.k) * (v.ty); - - this.offsetX = (this.icon.x - this.window.x) * (this.y / this.fullHeight) * this.k + (this.icon.x - this.window.x) * this.j; - this.offsetY = this.iconMonitor.height - this.icon.height - this.window.y - this.height - this.expandHeight * (1 - this.k); - - if (this.EFFECT === 'sine') { - this.effectX = Math.sin((this.height - this.y) / this.fullHeight * Math.PI * 4) * this.window.width / 14 * this.k; - } else { - this.effectX = Math.sin(((this.height - this.y) / this.fullHeight) * 2 * Math.PI + Math.PI) * (this.window.x + this.window.width * v.tx - (this.icon.x + this.icon.width * v.tx)) / 7 * this.k; - } - } - - v.x = (this.x + this.offsetX + this.effectX) * propX; - v.y = (this.y + this.offsetY + this.effectY) * propY; - } - } -} - -class MagicLampMinimizeEffect extends AbstractCommonMagicLampEffect { - static { - GObject.registerClass(this); - } - - _init(params = {}) { - super._init(params); - - this.k = 0; - this.j = 0; - this.isMinimizeEffect = true; - - } - - destroy_actor(actor) { - Main.wm._shellwm.original_completed_minimize(actor); - } - - on_tick_elapsed(timer, msecs) { - if (Main.overview.visible) { - this.destroy(); - } - - this.progress = timer.get_progress(); - this.k = this.progress <= this.split ? this.progress * (1 / 1 / this.split) : 1; - this.j = this.progress > this.split ? (this.progress - this.split) * (1 / 1 / (1 - this.split)) : 0; - - this.actor.get_parent().queue_redraw(); - this.invalidate(); - } - - vfunc_modify_paint_volume(pv) { - return false; - } -} - -class MagicLampUnminimizeEffect extends AbstractCommonMagicLampEffect { - static { - GObject.registerClass(this); - } - - _init(params = {}) { - super._init(params); - - this.k = 1; - this.j = 1; - this.isMinimizeEffect = false; - } - - destroy_actor(actor) { - Main.wm._shellwm.original_completed_unminimize(actor); - } - - on_tick_elapsed(timer, msecs) { - if (Main.overview.visible) { - this.destroy(); - } - - this.progress = timer.get_progress(); - this.k = 1 - (this.progress > (1 - this.split) ? (this.progress - (1 - this.split)) * (1 / 1 / (1 - (1 - this.split))) : 0); - this.j = 1 - (this.progress <= (1 - this.split) ? this.progress * (1 / 1 / (1 - this.split)) : 1); - - this.actor.get_parent().queue_redraw(); - this.invalidate(); - } - - vfunc_modify_paint_volume(pv) { - return false; - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/metadata.json deleted file mode 100755 index 31b190ac..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Magic lamp effect inspired by the Compiz ones\n\nNB:\nIn case of update error please restart Gnome Shell (on Xorg press ALT+F2 then write r and press enter, on Wayland end the session and log in again)", - "name": "Compiz alike magic lamp effect", - "settings-schema": "org.gnome.shell.extensions.com.github.hermes83.compiz-alike-magic-lamp-effect", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/hermes83/compiz-alike-magic-lamp-effect", - "uuid": "compiz-alike-magic-lamp-effect@hermes83.github.com", - "version": 19 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/prefs.js deleted file mode 100755 index f9ea4720..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/prefs.js +++ /dev/null @@ -1,169 +0,0 @@ - -/* - * Compiz-alike-magic-lamp-effect for GNOME Shell - * - * Copyright (C) 2020 - * Mauro Pepe - * - * This file is part of the gnome-shell extension Compiz-alike-magic-lamp-effect. - * - * gnome-shell extension Compiz-alike-magic-lamp-effect is free software: you can - * redistribute it and/or modify it under the terms of the GNU - * General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * gnome-shell extension Compiz-alike-magic-lamp-effect is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gnome-shell extension Compiz-alike-magic-lamp-effect. If not, see - * . - */ -'use strict'; - -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; - -import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import { SettingsData } from './settings_data.js'; - -export default class Prefs extends ExtensionPreferences { - - fillPreferencesWindow(window) { - const settingsData = new SettingsData(this.getSettings()); - - const width = 750; - const height = 380; - window.set_default_size(width, height); - - const page = Adw.PreferencesPage.new(); - - const group1 = Adw.PreferencesGroup.new(); - this.effectComboBox = this.addComboBox(group1, "Effect", settingsData.EFFECT); - this.durationSlider = this.addSlider(group1, "Duration (ms)", settingsData.DURATION, 100.0, 1000.0, 0); - page.add(group1); - - const group2 = Adw.PreferencesGroup.new(); - this.xTilesSlider = this.addSlider(group2, "X Tiles", settingsData.X_TILES, 3.0, 50.0, 0); - this.yTilesSlider = this.addSlider(group2, "Y Tiles", settingsData.Y_TILES, 3.0, 50.0, 0); - page.add(group2); - - this.addResetButton(window, settingsData); - - window.add(page); - } - - addResetButton(window, settingsData) { - const button = new Gtk.Button({vexpand: true, valign: Gtk.Align.END}); - button.set_icon_name('edit-clear'); - - button.connect('clicked', () => { - settingsData.EFFECT.set("default"); - settingsData.DURATION.set(500.0); - settingsData.X_TILES.set(15.0); - settingsData.Y_TILES.set(20.0); - - this.effectComboBox.set_active(0); - this.durationSlider.set_value(settingsData.DURATION.get()); - this.xTilesSlider.set_value(settingsData.X_TILES.get()); - this.yTilesSlider.set_value(settingsData.Y_TILES.get()); - }); - - const header = this.findWidgetByType(window.get_content(), Adw.HeaderBar); - if (header) { - header.pack_start(button); - } - - return button; - } - - addSlider(group, labelText, settingsData, lower, upper, decimalDigits) { - const scale = new Gtk.Scale({ - digits: decimalDigits, - adjustment: new Gtk.Adjustment({lower: lower, upper: upper}), - value_pos: Gtk.PositionType.RIGHT, - hexpand: true, - halign: Gtk.Align.END - }); - scale.set_draw_value(true); - scale.set_value(settingsData.get()); - scale.connect('value-changed', (sw) => { - var newval = sw.get_value(); - if (newval != settingsData.get()) { - settingsData.set(newval); - } - }); - scale.set_size_request(400, 15); - - const row = Adw.ActionRow.new(); - row.set_title(labelText); - row.add_suffix(scale); - group.add(row); - - return scale; - } - - addComboBox(group, labelText, settingsData) { - let gtkComboBoxText = new Gtk.ComboBoxText({hexpand: true, halign: Gtk.Align.END}); - gtkComboBoxText.set_valign(Gtk.Align.CENTER); - - let activeIndex = 0; - let activeValue = settingsData.get(); - let values = ["default", "sine"]; - - for (let i = 0; i < values.length; i++) { - gtkComboBoxText.append_text(values[i]); - if (activeValue && activeValue == values[i]) { - activeIndex = i; - } - } - - gtkComboBoxText.set_active(activeIndex); - gtkComboBoxText.connect('changed', function (sw) { - var newval = values[sw.get_active()]; - if (newval != settingsData.get()) { - settingsData.set(newval); - } - }); - - const row = Adw.ActionRow.new(); - row.set_title(labelText); - row.add_suffix(gtkComboBoxText); - group.add(row); - - return gtkComboBoxText; - } - - addBooleanSwitch(group, labelText, settingsData) { - const gtkSwitch = new Gtk.Switch({hexpand: true, halign: Gtk.Align.END}); - gtkSwitch.set_active(settingsData.get()); - gtkSwitch.set_valign(Gtk.Align.CENTER); - gtkSwitch.connect('state-set', (sw) => { - var newval = sw.get_active(); - if (newval != settingsData.get()) { - settingsData.set(newval); - } - }); - - const row = Adw.ActionRow.new(); - row.set_title(labelText); - row.add_suffix(gtkSwitch); - group.add(row); - - return gtkSwitch; - } - - findWidgetByType(parent, type) { - for (const child of [...parent]) { - if (child instanceof type) return child; - - const match = this.findWidgetByType(child, type); - if (match) return match; - } - return null; - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/schemas/gschemas.compiled deleted file mode 100755 index 28447690..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/schemas/org.gnome.shell.extensions.com.github.hermes83.compiz-alike-magic-lamp-effect.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/schemas/org.gnome.shell.extensions.com.github.hermes83.compiz-alike-magic-lamp-effect.gschema.xml deleted file mode 100755 index 71a866de..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/schemas/org.gnome.shell.extensions.com.github.hermes83.compiz-alike-magic-lamp-effect.gschema.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - "default" - Effect - - - - - 400 - Duration - - - - - 10.0 - X Tiles - - - - - 10.0 - Y Tiles - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/settings_data.js b/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/settings_data.js deleted file mode 100755 index f089c3c1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/compiz-alike-magic-lamp-effect@hermes83.github.com/settings_data.js +++ /dev/null @@ -1,53 +0,0 @@ - -/* - * Compiz-alike-magic-lamp-effect for GNOME Shell - * - * Copyright (C) 2020 - * Mauro Pepe - * - * This file is part of the gnome-shell extension Compiz-alike-magic-lamp-effect. - * - * gnome-shell extension Compiz-alike-magic-lamp-effect is free software: you can - * redistribute it and/or modify it under the terms of the GNU - * General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * gnome-shell extension Compiz-alike-magic-lamp-effect is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gnome-shell extension Compiz-alike-magic-lamp-effect. If not, see - * . - */ -'use strict'; - -export class SettingsData { - constructor(settings) { - this.EFFECT = { - key: 'effect', - get: function () { return settings.get_string(this.key); }, - set: function (v) { settings.set_string(this.key, v); } - }; - - this.DURATION = { - key: 'duration', - get: function () { return settings.get_double(this.key); }, - set: function (v) { settings.set_double(this.key, v); } - }; - - this.X_TILES = { - key: 'x-tiles', - get: function () { return settings.get_double(this.key); }, - set: function (v) { settings.set_double(this.key, v); } - }; - - this.Y_TILES = { - key: 'y-tiles', - get: function () { return settings.get_double(this.key); }, - set: function (v) { settings.set_double(this.key, v); } - }; - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/COPYING b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/COPYING deleted file mode 100755 index d159169d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/README.md b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/README.md deleted file mode 100755 index b1b2cf19..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Dash to Dock -![screenshot](https://github.com/micheleg/dash-to-dock/raw/master/media/screenshot.jpg) - -## A dock for the GNOME Shell -This extension enhances the dash moving it out of the overview and transforming it in a dock for an easier launching of applications and a faster switching between windows and desktops without having to leave the desktop view. - -[](https://extensions.gnome.org/extension/307/dash-to-dock) - -For additional installation instructions and more information visit [https://micheleg.github.io/dash-to-dock/](https://micheleg.github.io/dash-to-dock/). - -## Installation from source - -The extension can be installed directly from source, either for the convenience of using git or to test the latest development version. Clone the desired branch with git - -### Build Dependencies - -To compile the stylesheet you'll need an implementation of SASS. Dash to Dock supports `dart-sass` (`sass`), `sassc`, and `ruby-sass`. Every distro should have at least one of these implementations, we recommend using `dart-sass` (`sass`) or `sassc` over `ruby-sass` as `ruby-sass` is deprecated. - -By default, Dash to Dock will attempt to build with `sassc`. To change this behavior set the `SASS` environment variable to either `dart` or `ruby`. - -```bash -export SASS=dart -# or... -export SASS=ruby -``` - -### Building - -Clone the repository or download the branch from github. A simple Makefile is included. - -Next use `make` to install the extension into your home directory. A Shell reload is required `Alt+F2 r Enter` under Xorg or under Wayland you may have to logout and login. The extension has to be enabled with *gnome-extensions-app* (GNOME Extensions) or with *dconf*. - -```bash -git clone https://github.com/micheleg/dash-to-dock.git -make -C dash-to-dock install -``` - -If `msgfmt` is not available on your system, you will see an error message like the following: - -```bash -make: msgfmt: No such file or directory -``` - -In this case install the `gettext` package from your distribution's repository. - - -## Bug Reporting - -Bugs should be reported to the Github bug tracker [https://github.com/micheleg/dash-to-dock/issues](https://github.com/micheleg/dash-to-dock/issues). - -## License -Dash to Dock Gnome Shell extension is distributed under the terms of the GNU General Public License, -version 2 or later. See the COPYING file for details. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/Settings.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/Settings.ui deleted file mode 100755 index d6bd65a4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/Settings.ui +++ /dev/null @@ -1,3099 +0,0 @@ - - - - - 1 - 0.050000000000000003 - 0.25 - - - 0 - 12 - 12 - 12 - 12 - vertical - - - 0 - - - 0 - 1 - 1 - none - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - When set to minimize, double clicking minimizes all the windows of the application. - 1 - 0 - 40 - - - - 0 - 1 - - - - - - 0 - 1 - Shift+Click action - 0 - - - 0 - 0 - - - - - - 0 - center - - Raise window - Minimize window - Launch new instance - Cycle through windows - Minimize or overview - Show window previews - Minimize or show previews - Focus or show previews - Focus or app spread - Focus, minimize or show previews - Focus, minimize or app spread - Quit - - - 1 - 0 - 2 - - - - - - - - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - Behavior for Middle-Click. - 1 - 0 - 40 - - - - 0 - 1 - - - - - - 0 - 1 - Middle-Click action - 0 - - - 0 - 0 - - - - - - 0 - center - - Raise window - Minimize window - Launch new instance - Cycle through windows - Minimize or overview - Show window previews - Minimize or show previews - Focus or show previews - Focus or app spread - Focus, minimize or show previews - Focus, minimize or app spread - Quit - - - 1 - 0 - 2 - - - - - - - - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - Behavior for Shift+Middle-Click. - 1 - 0 - 40 - - - - 0 - 1 - - - - - - 0 - 1 - Shift+Middle-Click action - 0 - - - 0 - 0 - - - - - - 0 - center - - Raise window - Minimize window - Launch new instance - Cycle through windows - Minimize or overview - Show window previews - Minimize or show previews - Focus or show previews - Focus or app spread - Focus, minimize or show previews - Focus, minimize or app spread - Quit - - - 1 - 0 - 2 - - - - - - - - - - - - - - - - - 1 - 0.01 - 0.10 - - - 0.33 - 1 - 0.01 - 0.10 - - - 10 - 1 - 5 - - - 1 - 1 - 0 - 12 - 12 - 12 - 12 - vertical - - - 0 - - - - 0 - none - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - vertical - 12 - - - 0 - 32 - - - 1 - 0 - 0 - center - Enable Unity7 like glossy backlit items - - - - - - center - - - - - - - Apply glossy effect. - - - - - 0 - - - 1 - 0 - 0 - start - Use dominant color - - - - - - - - - - 0 - 32 - - - - 1 - 0 - - - - - - 0 - 1 - 0 - Customize indicator style - fill - - - 0 - 0 - - - - - - - - 0 - 1 - vertical - 12 - - - 0 - 32 - - - 1 - 0 - 0 - Color - - - - - - 1 - - - - - - - 0 - 32 - - - 1 - 0 - 0 - Border color - - - - - - 1 - - - - - - - 0 - 32 - - - 1 - 0 - 0 - Border width - - - - - - dot_border_width_adjustment - - - - - - - - - - - - - - - - - - - - 1 - 0.050000000000000003 - 0.25 - - - 16 - 128 - 1 - 10 - - - 0.0 - 1 - 0.01 - 0.1 - - - 6 - 6 - 6 - 6 - - - - - 0 - 24 - 24 - 24 - 24 - vertical - 24 - - - 0 - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Show the dock on - - 0 - 0 - - - - - - 0 - 400 - center - - - 1 - 0 - - - - - - Show on all monitors - 12 - - - 0 - 2 - 2 - - - - - - - - - - - - - - - - 100 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - 0 - Position on screen - - - - - - 0 - 32 - - - Left - end - center - - - - - - - Bottom - center - - position_left_button - - - - - - Top - center - - - position_left_button - - - - - - Right - center - - position_left_button - - - - - - - - - - - - - - - - - - - 0 - - - - 0 - none - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Hide the dock when it obstructs a window of the current application. More refined settings are available. - 1 - 0 - - - 0 - 1 - - - - - - 0 - 1 - start - Intelligent autohide - - - 0 - 0 - - - - - - 0 - 6 - - - 1 - center - center - - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - 1 - 0 - 2 - - - - - - - - - - - - - - - - - 0 - - - - 0 - none - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Dock size limit - - - 0 - 0 - - - - - - 1 - baseline - 1 - dock_size_adjustment - 0 - 2 - right - - - - - - Panel mode: extend to the screen edge - 12 - - - 0 - 1 - 2 - - - - - - Place icons to the center - - 0 - 2 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Icon size limit - - - 0 - 0 - - - - - - 1 - baseline - 1 - icon_size_adjustment - 1 - 0 - right - - - 1 - 0 - - - - - - Fixed icon size: scroll to reveal other icons - 12 - - - 0 - 1 - 2 - - - - - - - - - - True - - - False - 12 - 12 - 12 - 12 - 32 - - - False - Preview size scale - 0 - - 0 - 0 - - - - - - 1 - 1 - preview_size_adjustment - 0 - 0 - 0 - 2 - right - - - - - - 0 - 1 - - - - - - - - - - - - - - - - - 0 - Position and size - - - - - - - 1 - - - 0 - 24 - 24 - 24 - 24 - vertical - 24 - - - 0 - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Show pinned applications - - - 0 - 0 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Show running applications - - - 0 - 0 - - - - - - Isolate workspaces - start - 12 - - - 0 - 2 - 2 - - - - - - Show urgent windows despite current workspace - start - 12 - - - 0 - 3 - 2 - - - - - - Isolate monitors - start - 12 - - - 0 - 4 - 2 - - - - - - 3 - Show open windows' previews - - 0 - 1 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Keep the focused application always visible in the dash - - - 0 - 0 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - 2 - - - - - - 0 - 1 - If disabled, these settings are accessible from gnome-tweak-tool or the extension website. - 1 - 0 - - - 0 - 1 - - - - - - 0 - 1 - start - Show <i>Applications</i> icon - 1 - - - 0 - 0 - - - - - - Move at beginning of the dock - start - 12 - - - 0 - 2 - 2 - - - - - - - 3 - - - 0 - start - Animate <i>Show Applications</i> - 1 - - - - 0 - 3 - 2 - - - - - - - 3 - - - 0 - start - Put <i>Show Applications</i> in a dock edge when using Panel mode - 1 - - - - 0 - 4 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Show trash can - - - 0 - 0 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Show volumes and devices - - - 0 - 0 - - - - - - Only if mounted - start - 12 - - - 0 - 1 - 1 - - - - - - Include network volumes - start - 12 - - - 0 - 2 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Isolate volumes, devices and trash windows from file manager - - - 0 - 0 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Wiggle urgent applications - - - 0 - 0 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Hide application tooltip - - - 0 - 0 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - - - - - - 0 - 1 - start - Show icons emblems - - - 0 - 0 - - - - - - - 0 - 1 - When enabled application icons will show notification counters and progress-bars (if Unity API is used). - 1 - 0 - - - 0 - 1 - - - - - - - Show the number of unread notifications - start - 12 - - - 0 - 2 - 2 - - - - - - - 3 - - - 0 - start - Application-provided counter overrides the notifications counter - - - - 0 - 3 - 2 - - - - - - - - - - - - - - - - - - - - 0 - Launchers - - - - - - - 2 - - - 0 - 24 - 24 - 24 - 24 - vertical - 24 - - - 0 - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Enable Super+(0-9) as shortcuts to activate apps. It can also be used together with Shift and Ctrl. - 1 - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - start - Use keyboard shortcuts to activate apps - - - 0 - 0 - - - - - - 0 - 6 - - - 1 - center - center - - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - 1 - 0 - 2 - - - - - - - - - - - - - - - - - 0 - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Behaviour when clicking on the icon of a running application. - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - start - Click action - 0 - - - 0 - 0 - - - - - - 0 - 6 - - - 1 - center - - - 0 - emblem-system-symbolic - - - - - - - - 0 - center - - Raise window - Minimize - Launch new instance - Cycle through windows - Minimize or overview - Show window previews - Minimize or show previews - Focus or show previews - Focus or app spread - Focus, minimize or show previews - Focus, minimize or app spread - - - - - 1 - 0 - 2 - - - - - - - - - - - - - - - - - 0 - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Behaviour when scrolling on the icon of an application. - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - start - Scroll action - - - 0 - 0 - - - - - - 0 - 6 - - - 0 - center - - Do nothing - Cycle through windows - Switch workspace - - - - - 1 - 0 - 2 - - - - - - - - - - - - - - - - - - - 0 - start - Behavior - - - - - - - 3 - - - 0 - 24 - 24 - 24 - 24 - vertical - 24 - - - 0 - - - - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - 2 - - - - - - 0 - 1 - start - Save space reducing padding and border radius. - - - - 0 - 1 - - - - - - 0 - 1 - start - Shrink the dash - - - 0 - 0 - - - - - - - - - - 100 - 80 - - - 0 - 32 - 12 - 12 - 12 - 12 - - - 1 - 0 - center - start - Force straight corner - - - - - - center - 3 - - - - - - - 100 - 80 - - - 0 - 32 - 12 - 12 - 12 - 12 - - - 1 - 0 - center - start - Show overview on startup - - - - - center - 3 - - - - - - - - - - - - - - - - 0 - - - - vertical - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Few customizations meant to integrate the dock with the default GNOME theme. Alternatively, specific options can be enabled below. - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - start - Use built-in theme - - - 0 - 0 - - - - - - end - center - - 1 - 0 - 2 - - - - - - - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Customize windows counter indicators - - - 0 - 0 - - - - - - 0 - 6 - - - 1 - center - center - - - - 0 - emblem-system-symbolic - - - - - - - - 0 - - Default - Dots - Squares - Dashes - Segmented - Solid - Ciliora - Metro - Binary - - - - - 1 - 0 - 2 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Set the background color for the dash. - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - start - Customize the dash color - - - 0 - 0 - - - - - - 0 - 6 - - - 1 - center - center - - - - - - end - center - - - - 1 - 0 - 2 - - - - - - - - - - - - 0 - vertical - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Tune the dash background opacity. - - - - 0 - 1 - - - - - - 0 - 1 - start - Customize opacity - - - 0 - 0 - - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - 0 - center - - Default - Fixed - Dynamic - - - - - 1 - 0 - 2 - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Opacity - - - - - 1 - 1 - custom_opacity_adjustement - - 0 - 0 - 0 - 2 - right - - - - - - - - - - - - - - - - - - - - - - - 0 - Appearance - - - - - - - 4 - - - 0 - 0 - 24 - 24 - 1 - 1 - vertical - 5 - - - - - - 0 - <b>Dash to Dock</b> - 1 - - - - - 0 - center - - - 0 - end - version: - - - - - 0 - start - ... - - - - - - - 0 - Moves the dash out of the overview transforming it in a dock - center - 1 - 0 - - - - - 0 - center - 5 - - - 0 - Created by - - - - - Michele (<a href="mailto:micxgx@gmail.com">micxgx@gmail.com</a>) - 1 - - - - - - - Webpage - 1 - center - - https://micheleg.github.io/dash-to-dock/ - - - - - 1 - end - <span size="small">This program comes with ABSOLUTELY NO WARRANTY. -See the <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, version 2 or later</a> for details.</span> - 1 - center - 1 - 0 - - - - - - - 0 - About - - - - - - - 1 - 0.01 - 0.10000000000000001 - - - 1 - 0.01 - 0.10000000000000001 - - - 1 - 1 - 0 - 12 - 12 - 12 - 12 - vertical - - - 0 - - - - 0 - none - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - vertical - 12 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - Customize minimum and maximum opacity values - fill - 0 - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Minimum opacity - - - - - 1 - 1 - min_opacity_adjustement - - 0 - 0 - 0 - 2 - right - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Maximum opacity - - - - - 1 - 1 - max_opacity_adjustement - - 0 - 0 - 0 - 2 - right - - - - - - - - - - - - - - - - - - - 1000 - 50 - 250 - - - 10 - 0.25 - 1 - - - 1 - 1 - 12 - 12 - 12 - 12 - vertical - - - - - none - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - 2 - - - - - - 0 - 1 - Number overlay - - - 0 - 0 - - - - - - 0 - Temporarily show the application numbers over the icons, corresponding to the shortcut. - 1 - 0 - 40 - - - - 0 - 1 - - - - - - - - - - 100 - 80 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - center - - 1 - 0 - 2 - - - - - - 0 - 1 - start - Show the dock if it is hidden - - - 0 - 0 - - - - - - 0 - If using autohide, the dock will appear for a short time when triggering the shortcut. - 1 - 0 - 40 - - - - 0 - 1 - - - - - - - - - - 100 - 80 - - - 12 - 12 - 12 - 12 - 32 - - - center - 12 - - 1 - 0 - - - - - - 0 - 1 - Shortcut for the options above - - - 0 - 0 - - - - - - 0 - Syntax: <Shift>, <Ctrl>, <Alt>, <Super> - 1 - 0 - 40 - - - - 0 - 1 - - - - - - - - - - - - - - - 12 - 12 - 12 - 12 - 1 - 6 - 32 - - - end - shortcut_time_adjustment - 3 - - 1 - 0 - - - - - - 0 - 1 - Hide timeout (s) - - - 0 - 0 - - - - - - - - - - - - - - - - - 1 - 0.050000000000000003 - 0.25 - - - 1 - 1 - 0 - 12 - 12 - 12 - 12 - vertical - - - 0 - - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Show the dock by mouse hover on the screen edge. - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - Autohide - - - 0 - 0 - - - - - - end - center - - 1 - 0 - 2 - - - - - - Push to show: require pressure to show the dock - - - 0 - 3 - 2 - - - - - - Enable in fullscreen mode - 12 - - - 0 - 2 - 2 - - - - - - Show dock for urgent notifications - 12 - - - 0 - 4 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - 1 - start - Show the dock when it doesn't obstruct application windows. - 1 - 0 - - - - 0 - 1 - - - - - - 0 - 1 - Dodge windows - - - 0 - 0 - - - - - - end - center - - 1 - 0 - 2 - - - - - - 0 - vertical - - - All windows - 12 - - - - - - - Only focused application's windows - all_windows_radio_button - - - - - - Only maximized windows - all_windows_radio_button - - - - - - Always on top - all_windows_radio_button - - - - - 0 - 2 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 1 - 6 - 32 - - - end - animation_time_adjustment - 3 - - 1 - 0 - - - - - - 0 - 1 - Animation duration (s) - - - 0 - 0 - - - - - - end - hide_timeout_adjustment - 3 - - 1 - 1 - - - - - - end - show_timeout_adjustment - 3 - - 1 - 2 - - - - - - 0.000 - pressure_threshold_adjustment - - 1 - 3 - - - - - - 0 - 1 - Hide timeout (s) - - - 0 - 1 - - - - - - 0 - 1 - Show timeout (s) - - - 0 - 2 - - - - - - 0 - 1 - Pressure threshold - - - 0 - 3 - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appIconIndicators.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appIconIndicators.js deleted file mode 100755 index e38510d1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appIconIndicators.js +++ /dev/null @@ -1,1209 +0,0 @@ -import { - Clutter, - GdkPixbuf, - Gio, - GObject, - Pango, - St, -} from './dependencies/gi.js'; - -import {Main} from './dependencies/shell/ui.js'; - -import { - Docking, - Utils, -} from './imports.js'; - -const {cairo: Cairo} = imports; - -const RunningIndicatorStyle = Object.freeze({ - DEFAULT: 0, - DOTS: 1, - SQUARES: 2, - DASHES: 3, - SEGMENTED: 4, - SOLID: 5, - CILIORA: 6, - METRO: 7, - BINARY: 8, -}); - -const MAX_WINDOWS_CLASSES = 4; - - -/* - * This is the main indicator class to be used. The desired bahviour is - * obtained by composing the desired classes below based on the settings. - * - */ -export class AppIconIndicator { - constructor(source) { - this._indicators = []; - - // Choose the style for the running indicators - let runningIndicator = null; - let runningIndicatorStyle; - - const {settings} = Docking.DockManager; - if (settings.applyCustomTheme) - runningIndicatorStyle = RunningIndicatorStyle.DOTS; - else - ({runningIndicatorStyle} = settings); - - if (settings.showIconsEmblems && - !Docking.DockManager.getDefault().notificationsMonitor.dndMode) { - const unityIndicator = new UnityIndicator(source); - this._indicators.push(unityIndicator); - } - - switch (runningIndicatorStyle) { - case RunningIndicatorStyle.DEFAULT: - runningIndicator = new RunningIndicatorDefault(source); - break; - - case RunningIndicatorStyle.DOTS: - runningIndicator = new RunningIndicatorDots(source); - break; - - case RunningIndicatorStyle.SQUARES: - runningIndicator = new RunningIndicatorSquares(source); - break; - - case RunningIndicatorStyle.DASHES: - runningIndicator = new RunningIndicatorDashes(source); - break; - - case RunningIndicatorStyle.SEGMENTED: - runningIndicator = new RunningIndicatorSegmented(source); - break; - - case RunningIndicatorStyle.SOLID: - runningIndicator = new RunningIndicatorSolid(source); - break; - - case RunningIndicatorStyle.CILIORA: - runningIndicator = new RunningIndicatorCiliora(source); - break; - - case RunningIndicatorStyle.METRO: - runningIndicator = new RunningIndicatorMetro(source); - break; - case RunningIndicatorStyle.BINARY: - runningIndicator = new RunningIndicatorBinary(source); - break; - - default: - runningIndicator = new RunningIndicatorBase(source); - } - - this._indicators.push(runningIndicator); - } - - update() { - for (let i = 0; i < this._indicators.length; i++) { - const indicator = this._indicators[i]; - indicator.update(); - } - } - - destroy() { - for (let i = 0; i < this._indicators.length; i++) { - const indicator = this._indicators[i]; - indicator.destroy(); - } - } -} - -/* - * Base class to be inherited by all indicators of any kind -*/ -class IndicatorBase { - constructor(source) { - this._source = source; - this._signalsHandler = new Utils.GlobalSignalsHandler(this._source); - } - - update() { - } - - destroy() { - this._source = null; - this._signalsHandler.destroy(); - this._signalsHandler = null; - } -} - -/* - * A base indicator class for running style, from which all other EunningIndicators should derive, - * providing some basic methods, variables definitions and their update, css style classes handling. - * - */ -class RunningIndicatorBase extends IndicatorBase { - constructor(source) { - super(source); - - this._side = Utils.getPosition(); - this._dominantColorExtractor = new DominantColorExtractor(this._source.app); - this._signalsHandler.add(this._source, 'notify::running', () => this.update()); - this._signalsHandler.add(this._source, 'notify::focused', () => this.update()); - this._signalsHandler.add(this._source, 'notify::windows-count', () => this._updateCounterClass()); - this.update(); - } - - get _number() { - return Math.min(this._source.windowsCount, MAX_WINDOWS_CLASSES); - } - - update() { - this._updateCounterClass(); - this._updateDefaultDot(); - } - - _updateCounterClass() { - for (let i = 1; i <= MAX_WINDOWS_CLASSES; i++) { - const className = `running${i}`; - if (i !== this._number) - this._source.remove_style_class_name(className); - else - this._source.add_style_class_name(className); - } - } - - _updateDefaultDot() { - if (this._source.running) - this._source._dot.show(); - else - this._source._dot.hide(); - } - - _hideDefaultDot() { - // I use opacity to hide the default dot because the show/hide function - // are used by the parent class. - this._source._dot.opacity = 0; - } - - _restoreDefaultDot() { - this._source._dot.opacity = 255; - } - - _enableBacklight() { - const colorPalette = this._dominantColorExtractor._getColorPalette(); - - // Fallback - if (!colorPalette) { - this._source._iconContainer.set_style( - 'border-radius: 5px;' + - 'background-gradient-direction: vertical;' + - 'background-gradient-start: #e0e0e0;' + - 'background-gradient-end: darkgray;' - ); - - return; - } - - this._source._iconContainer.set_style( - `${'border-radius: 5px;' + - 'background-gradient-direction: vertical;' + - 'background-gradient-start: '}${colorPalette.original};` + - `background-gradient-end: ${colorPalette.darker};` - ); - } - - _disableBacklight() { - this._source._iconContainer.set_style(null); - } - - destroy() { - this._disableBacklight(); - // Remove glossy background if the children still exists - if (this._source._iconContainer.get_children().length > 1) - this._source._iconContainer.get_children()[1].set_style(null); - this._restoreDefaultDot(); - - super.destroy(); - } -} - -// We add a css class so third parties themes can limit their indicaor customization -// to the case we do nothing -class RunningIndicatorDefault extends RunningIndicatorBase { - constructor(source) { - super(source); - this._source.add_style_class_name('default'); - } - - destroy() { - this._source.remove_style_class_name('default'); - super.destroy(); - } -} - -const IndicatorDrawingArea = GObject.registerClass( -class IndicatorDrawingArea extends St.DrawingArea { - vfunc_allocate(box) { - if (box.x1 !== 0 || box.y1 !== 0) - return super.vfunc_allocate(box); - - // We assume that the are is a rectangle in the operations below: - const size = Math.min(box.get_width(), box.get_height()); - box.x2 = size; - box.y2 = size; - this.set_allocation(box); - - return super.vfunc_allocate(box); - } -}); - -class RunningIndicatorDots extends RunningIndicatorBase { - constructor(source) { - super(source); - - this._hideDefaultDot(); - - this._area = new IndicatorDrawingArea({ - x_expand: true, - y_expand: true, - }); - - // We draw for the bottom case and rotate the canvas for other placements - // set center of rotatoins to the center - this._area.set_pivot_point(0.5, 0.5); - - switch (this._side) { - case St.Side.TOP: - this._area.rotation_angle_z = 180; - break; - - case St.Side.BOTTOM: - // nothing - break; - - case St.Side.LEFT: - this._area.rotation_angle_z = 90; - break; - - case St.Side.RIGHT: - this._area.rotation_angle_z = -90; - break; - } - - this._area.connect('repaint', this._updateIndicator.bind(this)); - this._source._iconContainer.add_child(this._area); - - const keys = ['custom-theme-running-dots-color', - 'custom-theme-running-dots-border-color', - 'custom-theme-running-dots-border-width', - 'custom-theme-customize-running-dots', - 'unity-backlit-items', - 'apply-glossy-effect', - 'running-indicator-dominant-color']; - - keys.forEach(function (key) { - this._signalsHandler.add( - Docking.DockManager.settings, - `changed::${key}`, - this.update.bind(this) - ); - }, this); - - // Apply glossy background - // TODO: move to enable/disableBacklit to apply itonly to the running apps? - // TODO: move to css class for theming support - const {extension} = Docking.DockManager; - this._glossyBackgroundStyle = `background-image: url('${extension.path}/media/glossy.svg');` + - 'background-size: contain;'; - } - - update() { - super.update(); - - // Enable / Disable the backlight of running apps - if (!Docking.DockManager.settings.applyCustomTheme && - Docking.DockManager.settings.unityBacklitItems) { - const [icon] = this._source._iconContainer.get_children(); - icon.set_style( - Docking.DockManager.settings.applyGlossyEffect - ? this._glossyBackgroundStyle : null); - if (this._source.running) - this._enableBacklight(); - else - this._disableBacklight(); - } else { - this._disableBacklight(); - this._source._iconContainer.get_children()[1].set_style(null); - } - - if (this._area) - this._area.queue_repaint(); - } - - _computeStyle() { - const [width, height] = this._area.get_surface_size(); - this._width = height; - this._height = width; - - // By defaut re-use the style - background color, and border width and color - - // of the default dot - const themeNode = this._source._dot.get_theme_node(); - this._borderColor = themeNode.get_border_color(this._side); - this._borderWidth = themeNode.get_border_width(this._side); - this._bodyColor = themeNode.get_background_color(); - - const {settings} = Docking.DockManager; - if (!settings.applyCustomTheme) { - // Adjust for the backlit case - if (settings.unityBacklitItems) { - // Use dominant color for dots too if the backlit is enables - const colorPalette = this._dominantColorExtractor._getColorPalette(); - - // Slightly adjust the styling - this._borderWidth = 2; - - if (colorPalette) { - [, this._borderColor] = Clutter.color_from_string(colorPalette.lighter); - [, this._bodyColor] = Clutter.color_from_string(colorPalette.darker); - } else { - // Fallback - [, this._borderColor] = Clutter.color_from_string('white'); - [, this._bodyColor] = Clutter.color_from_string('gray'); - } - } - - // Apply dominant color if requested - if (settings.runningIndicatorDominantColor) { - const colorPalette = this._dominantColorExtractor._getColorPalette(); - if (colorPalette) - [, this._bodyColor] = Clutter.color_from_string(colorPalette.original); - else - // Fallback - [, this._bodyColor] = Clutter.color_from_string(settings.customThemeRunningDotsColor); - } - - // Finally, use customize style if requested - if (settings.customThemeCustomizeRunningDots) { - [, this._borderColor] = Clutter.color_from_string(settings.customThemeRunningDotsBorderColor); - this._borderWidth = settings.customThemeRunningDotsBorderWidth; - [, this._bodyColor] = Clutter.color_from_string(settings.customThemeRunningDotsColor); - } - } - - // Define the radius as an arbitrary size, but keep large enough to account - // for the drawing of the border. - this._radius = Math.max(this._width / 22, this._borderWidth / 2); - this._padding = 0; // distance from the margin - this._spacing = this._radius + this._borderWidth; // separation between the dots - } - - _updateIndicator() { - const cr = this._area.get_context(); - - this._computeStyle(); - this._drawIndicator(cr); - cr.$dispose(); - } - - _drawIndicator(cr) { - // Draw the required numbers of dots - const n = this._number; - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - // draw for the bottom case: - cr.translate( - (this._width - (2 * n) * this._radius - (n - 1) * this._spacing) / 2, - this._height - this._padding); - - for (let i = 0; i < n; i++) { - cr.newSubPath(); - cr.arc((2 * i + 1) * this._radius + i * this._spacing, - -this._radius - this._borderWidth / 2, - this._radius, 0, 2 * Math.PI); - } - - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - - destroy() { - this._area.destroy(); - super.destroy(); - } -} - -// Adapted from dash-to-panel by Jason DeRose -// https://github.com/jderose9/dash-to-panel -class RunningIndicatorCiliora extends RunningIndicatorDots { - _drawIndicator(cr) { - if (this._source.running) { - const size = Math.max(this._width / 20, this._borderWidth); - const spacing = size; // separation between the dots - const lineLength = this._width - (size * (this._number - 1)) - (spacing * (this._number - 1)); - let padding = this._borderWidth; - // For the backlit case here we don't want the outer border visible - if (Docking.DockManager.settings.unityBacklitItems && - !Docking.DockManager.settings.customThemeCustomizeRunningDots) - padding = 0; - const yOffset = this._height - padding - size; - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - cr.translate(0, yOffset); - cr.newSubPath(); - cr.rectangle(0, 0, lineLength, size); - for (let i = 1; i < this._number; i++) { - cr.newSubPath(); - cr.rectangle(lineLength + (i * spacing) + ((i - 1) * size), 0, size, size); - } - - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - } -} - -// Adapted from dash-to-panel by Jason DeRose -// https://github.com/jderose9/dash-to-panel -class RunningIndicatorSegmented extends RunningIndicatorDots { - _drawIndicator(cr) { - if (this._source.running) { - const size = Math.max(this._width / 20, this._borderWidth); - const spacing = Math.ceil(this._width / 18); // separation between the dots - const dashLength = Math.ceil((this._width - ((this._number - 1) * spacing)) / this._number); - let padding = this._borderWidth; - // For the backlit case here we don't want the outer border visible - if (Docking.DockManager.settings.unityBacklitItems && - !Docking.DockManager.settings.customThemeCustomizeRunningDots) - padding = 0; - const yOffset = this._height - padding - size; - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - cr.translate(0, yOffset); - for (let i = 0; i < this._number; i++) { - cr.newSubPath(); - cr.rectangle(i * dashLength + i * spacing, 0, dashLength, size); - } - - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - } -} - -// Adapted from dash-to-panel by Jason DeRose -// https://github.com/jderose9/dash-to-panel -class RunningIndicatorSolid extends RunningIndicatorDots { - _drawIndicator(cr) { - if (this._source.running) { - const size = Math.max(this._width / 20, this._borderWidth); - let padding = this._borderWidth; - // For the backlit case here we don't want the outer border visible - if (Docking.DockManager.settings.unityBacklitItems && - !Docking.DockManager.settings.customThemeCustomizeRunningDots) - padding = 0; - const yOffset = this._height - padding - size; - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - cr.translate(0, yOffset); - cr.newSubPath(); - cr.rectangle(0, 0, this._width, size); - - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - } -} - -// Adapted from dash-to-panel by Jason DeRose -// https://github.com/jderose9/dash-to-panel -class RunningIndicatorSquares extends RunningIndicatorDots { - _drawIndicator(cr) { - if (this._source.running) { - const size = Math.max(this._width / 11, this._borderWidth); - const padding = this._borderWidth; - const spacing = Math.ceil(this._width / 18); // separation between the dots - const yOffset = this._height - padding - size; - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - cr.translate( - Math.floor((this._width - this._number * size - (this._number - 1) * spacing) / 2), - yOffset); - - for (let i = 0; i < this._number; i++) { - cr.newSubPath(); - cr.rectangle(i * size + i * spacing, 0, size, size); - } - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - } -} - -// Adapted from dash-to-panel by Jason DeRose -// https://github.com/jderose9/dash-to-panel -class RunningIndicatorDashes extends RunningIndicatorDots { - _drawIndicator(cr) { - if (this._source.running) { - const size = Math.max(this._width / 20, this._borderWidth); - const padding = this._borderWidth; - const spacing = Math.ceil(this._width / 18); // separation between the dots - const dashLength = Math.floor(this._width / 4) - spacing; - const yOffset = this._height - padding - size; - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - cr.translate( - Math.floor((this._width - this._number * dashLength - (this._number - 1) * spacing) / 2), - yOffset); - - for (let i = 0; i < this._number; i++) { - cr.newSubPath(); - cr.rectangle(i * dashLength + i * spacing, 0, dashLength, size); - } - - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - } -} - -// Adapted from dash-to-panel by Jason DeRose -// https://github.com/jderose9/dash-to-panel -class RunningIndicatorMetro extends RunningIndicatorDots { - constructor(source) { - super(source); - this._source.add_style_class_name('metro'); - } - - destroy() { - this._source.remove_style_class_name('metro'); - super.destroy(); - } - - _drawIndicator(cr) { - if (this._source.running) { - const size = Math.max(this._width / 20, this._borderWidth); - let padding = 0; - // For the backlit case here we don't want the outer border visible - if (Docking.DockManager.settings.unityBacklitItems && - !Docking.DockManager.settings.customThemeCustomizeRunningDots) - padding = 0; - const yOffset = this._height - padding - size; - - const n = this._number; - if (n <= 1) { - cr.translate(0, yOffset); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.newSubPath(); - cr.rectangle(0, 0, this._width, size); - cr.fill(); - } else { - // need to scale with the SVG for the stacked highlight - const blackenedLength = (1 / 48) * this._width; - const darkenedLength = this._source.focused - ? (2 / 48) * this._width : (10 / 48) * this._width; - const blackenedColor = this._bodyColor.shade(.3); - const darkenedColor = this._bodyColor.shade(.7); - - cr.translate(0, yOffset); - - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.newSubPath(); - cr.rectangle(0, 0, this._width - darkenedLength - blackenedLength, size); - cr.fill(); - Utils.cairoSetSourceColor(cr, blackenedColor); - cr.newSubPath(); - cr.rectangle(this._width - darkenedLength - blackenedLength, 0, 1, size); - cr.fill(); - Utils.cairoSetSourceColor(cr, darkenedColor); - cr.newSubPath(); - cr.rectangle(this._width - darkenedLength, 0, darkenedLength, size); - cr.fill(); - } - } - } -} - -class RunningIndicatorBinary extends RunningIndicatorDots { - _drawIndicator(cr) { - // Draw the required numbers of dots - const n = Math.min(15, this._source.windowsCount); - - if (this._source.running) { - const size = Math.max(this._width / 11, this._borderWidth); - const spacing = Math.ceil(this._width / 18); - const yOffset = this._height - size; - const binaryValue = String(`0000${(n >>> 0).toString(2)}`).slice(-4); - - cr.setLineWidth(this._borderWidth); - Utils.cairoSetSourceColor(cr, this._borderColor); - - cr.translate(Math.floor((this._width - 4 * size - (4 - 1) * spacing) / 2), yOffset); - for (let i = 0; i < binaryValue.length; i++) { - if (binaryValue[i] === '1') { - cr.newSubPath(); - cr.arc((2 * i + 1) * this._radius + i * spacing, - -this._radius - this._borderWidth / 2, - this._radius, 0, 2 * Math.PI); - } else { - cr.newSubPath(); - cr.rectangle(i * size + i * spacing, - -this._radius - this._borderWidth / 2 - size / 5, - size, size / 3); - } - } - cr.strokePreserve(); - Utils.cairoSetSourceColor(cr, this._bodyColor); - cr.fill(); - } - } -} - -/* - * Unity like notification and progress indicators - */ -class UnityIndicator extends IndicatorBase { - static defaultProgressBar = { - // default values for the progress bar itself - background: { - colorStart: {red: 204, green: 204, blue: 204, alpha: 255}, - colorEnd: null, - }, - border: { - colorStart: {red: 230, green: 230, blue: 230, alpha: 255}, - colorEnd: null, - }, - }; - - static defaultProgressBarTrack = { - // default values for the progress bar track - background: { - colorStart: {red: 64, green: 64, blue: 64, alpha: 255}, - colorEnd: {red: 89, green: 89, blue: 89, alpha: 255}, - offsetStart: 0.4, - offsetEnd: 0.9, - }, - border: { - colorStart: {red: 128, green: 128, blue: 128, alpha: 26}, - colorEnd: {red: 204, green: 204, blue: 204, alpha: 102}, - offsetStart: 0.5, - offsetEnd: 0.9, - }, - }; - - constructor(source) { - super(source); - - this._notificationBadgeLabel = new St.Label(); - this._notificationBadgeBin = new St.Bin({ - child: this._notificationBadgeLabel, - x_align: Clutter.ActorAlign.END, - y_align: Clutter.ActorAlign.START, - x_expand: true, y_expand: true, - }); - this._notificationBadgeLabel.add_style_class_name('notification-badge'); - this._notificationBadgeLabel.clutter_text.ellipsize = Pango.EllipsizeMode.MIDDLE; - this._notificationBadgeBin.hide(); - - this._source._iconContainer.add_child(this._notificationBadgeBin); - this.updateNotificationBadgeStyle(); - - const {remoteModel, notificationsMonitor} = Docking.DockManager.getDefault(); - const remoteEntry = remoteModel.lookupById(this._source.app.id); - this._remoteEntry = remoteEntry; - - this._signalsHandler.add([ - remoteEntry, - ['count-changed', 'count-visible-changed'], - () => this._updateNotificationsCount(), - ], [ - remoteEntry, - ['progress-changed', 'progress-visible-changed'], - (sender, {progress, progress_visible: progressVisible}) => - this.setProgress(progressVisible ? progress : -1), - ], [ - remoteEntry, - 'urgent-changed', - (sender, {urgent}) => this.setUrgent(urgent), - ], [ - notificationsMonitor, - 'changed', - () => this._updateNotificationsCount(), - ], [ - St.ThemeContext.get_for_stage(global.stage), - 'changed', - this.updateNotificationBadgeStyle.bind(this), - ], [ - this._source._iconContainer, - 'notify::size', - this.updateNotificationBadgeStyle.bind(this), - ]); - } - - destroy() { - this._notificationBadgeBin.destroy(); - this._notificationBadgeBin = null; - this._hideProgressOverlay(); - this.setUrgent(false); - this._remoteEntry = null; - - super.destroy(); - } - - updateNotificationBadgeStyle() { - const themeContext = St.ThemeContext.get_for_stage(global.stage); - const fontDesc = themeContext.get_font(); - const defaultFontSize = fontDesc.get_size() / 1024; - let fontSize = defaultFontSize * 0.9; - const {iconSize} = Main.overview.dash; - const defaultIconSize = Docking.DockManager.settings.get_default_value( - 'dash-max-icon-size').unpack(); - - if (!fontDesc.get_size_is_absolute()) { - // fontSize was exprimed in points, so convert to pixel - fontSize /= 0.75; - } - - let sizeMultiplier; - if (iconSize < defaultIconSize) { - sizeMultiplier = Math.max(24, Math.min(iconSize + - iconSize * 0.3, defaultIconSize)) / defaultIconSize; - } else { - sizeMultiplier = iconSize / defaultIconSize; - } - - fontSize = Math.round(sizeMultiplier * fontSize); - const leftMargin = Math.round(sizeMultiplier * 3); - - this._notificationBadgeLabel.set_style( - `font-size: ${fontSize}px;` + - `margin-left: ${leftMargin}px` - ); - } - - _notificationBadgeCountToText(count) { - if (count <= 9999) { - return count.toString(); - } else if (count < 1e5) { - const thousands = count / 1e3; - return `${thousands.toFixed(1).toString()}k`; - } else if (count < 1e6) { - const thousands = count / 1e3; - return `${thousands.toFixed(0).toString()}k`; - } else if (count < 1e8) { - const millions = count / 1e6; - return `${millions.toFixed(1).toString()}M`; - } else if (count < 1e9) { - const millions = count / 1e6; - return `${millions.toFixed(0).toString()}M`; - } else { - const billions = count / 1e9; - return `${billions.toFixed(1).toString()}B`; - } - } - - _updateNotificationsCount() { - const remoteCount = this._remoteEntry['count-visible'] - ? this._remoteEntry.count ?? 0 : 0; - - if (remoteCount > 0 && - Docking.DockManager.settings.applicationCounterOverridesNotifications) { - this.setNotificationCount(remoteCount); - return; - } - - const {notificationsMonitor} = Docking.DockManager.getDefault(); - const notificationsCount = notificationsMonitor.getAppNotificationsCount( - this._source.app.id); - - this.setNotificationCount(remoteCount + notificationsCount); - } - - setNotificationCount(count) { - if (count > 0) { - const text = this._notificationBadgeCountToText(count); - this._notificationBadgeLabel.set_text(text); - this._notificationBadgeBin.show(); - } else { - this._notificationBadgeBin.hide(); - } - } - - _showProgressOverlay() { - if (this._progressOverlayArea) { - this._updateProgressOverlay(); - return; - } - - this._progressOverlayArea = new St.DrawingArea({x_expand: true, y_expand: true}); - this._progressOverlayArea.add_style_class_name('progress-bar'); - this._progressOverlayArea.connect('repaint', () => { - this._drawProgressOverlay(this._progressOverlayArea); - }); - - this._source._iconContainer.add_child(this._progressOverlayArea); - this._updateProgressOverlay(); - } - - _hideProgressOverlay() { - this._progressOverlayArea?.destroy(); - this._progressOverlayArea = null; - } - - _updateProgressOverlay() { - this._progressOverlayArea?.queue_repaint(); - } - - _readGradientData(node, elementName, defaultValues) { - const output = { - colorStart: defaultValues.colorStart, - colorEnd: defaultValues.colorEnd, - offsetStart: defaultValues.offsetStart ?? 0.0, - offsetEnd: defaultValues.offsetEnd ?? 1.0, - }; - - const [hasElementName, elementNameValue] = node.lookup_color(elementName, false); - if (hasElementName) { - output.colorStart = elementNameValue; - output.colorEnd = null; - } else { - const [hasColorStart, colorStartValue] = node.lookup_color(`${elementName}-color-start`, false); - const [hasColorEnd, colorEndValue] = node.lookup_color(`${elementName}-color-end`, false); - if (hasColorStart && hasColorEnd) { - output.colorStart = colorStartValue; - output.colorEnd = colorEndValue; - } - } - - const [hasOffsetStart, offsetStartvalue] = node.lookup_color(`${elementName}-offset-start`, false); - if (hasOffsetStart) - output.offsetStart = offsetStartvalue; - - const [hasOffsetEnd, offsetEndValue] = node.lookup_color(`${elementName}-offset-end`, false); - if (hasOffsetEnd) - output.offsetEnd = offsetEndValue; - - return output; - } - - _readElementData(node, elementName, defaultValues) { - const defaultLineWidth = defaultValues.lineWidth ?? 1.0; - const [hasValue, lineWidth] = node.lookup_double(`${elementName}-line-width`, false); - - return { - background: this._readGradientData(node, `${elementName}-background`, defaultValues.background), - border: this._readGradientData(node, `${elementName}-border`, defaultValues.border), - lineWidth: hasValue ? lineWidth : defaultLineWidth, - }; - } - - _createGradient(values, x0, y0, x1, y1) { - if (values.colorEnd) { - const gradient = new Cairo.LinearGradient(x0, y0, x1, y1); - gradient.addColorStopRGBA(values.offsetStart, - values.colorStart.red / 255, - values.colorStart.green / 255, - values.colorStart.blue / 255, - values.colorStart.alpha / 255); - gradient.addColorStopRGBA(values.offsetEnd, - values.colorEnd.red / 255, - values.colorEnd.green / 255, - values.colorEnd.blue / 255, - values.colorEnd.alpha / 255); - return gradient; - } else { - const gradient = Cairo.SolidPattern.createRGBA(values.colorStart.red / 255, - values.colorStart.green / 255, - values.colorStart.blue / 255, - values.colorStart.alpha / 255); - return gradient; - } - } - - _drawProgressOverlay(area) { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const [surfaceWidth, surfaceHeight] = area.get_surface_size(); - const cr = area.get_context(); - - const iconSize = this._source.icon.iconSize * scaleFactor; - - let x = Math.floor((surfaceWidth - iconSize) / 2); - let y = Math.floor((surfaceHeight - iconSize) / 2); - - const baseLineWidth = Math.floor(Number(scaleFactor)); - const padding = Math.floor(iconSize * 0.05); - let width = iconSize - 2.0 * padding; - let height = Math.floor(Math.min(18.0 * scaleFactor, 0.20 * iconSize)); - x += padding; - y += iconSize - height - padding; - - const node = this._progressOverlayArea.get_theme_node(); - - const progressBarTrack = this._readElementData(node, - '-progress-bar-track', - UnityIndicator.defaultProgressBarTrack); - - const progressBar = this._readElementData(node, - '-progress-bar', - UnityIndicator.defaultProgressBar); - - // Draw the track - let lineWidth = baseLineWidth * progressBarTrack.lineWidth; - cr.setLineWidth(lineWidth); - - x += lineWidth; - y += lineWidth; - width -= 2.0 * lineWidth; - height -= 2.0 * lineWidth; - - let fill = this._createGradient(progressBarTrack.background, 0, y, 0, y + height); - let stroke = this._createGradient(progressBarTrack.border, 0, y, 0, y + height); - Utils.drawRoundedLine(cr, x + lineWidth / 2.0, - y + lineWidth / 2.0, width, height, true, true, stroke, fill); - - // Draw the finished bar - lineWidth = baseLineWidth * progressBar.lineWidth; - cr.setLineWidth(lineWidth); - - x += lineWidth; - y += lineWidth; - width -= 2.0 * lineWidth; - height -= 2.0 * lineWidth; - - const finishedWidth = Math.ceil(this._progress * width); - fill = this._createGradient(progressBar.background, 0, y, 0, y + height); - stroke = this._createGradient(progressBar.border, 0, y, 0, y + height); - - if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) { - Utils.drawRoundedLine(cr, - x + lineWidth / 2.0 + width - finishedWidth, y + lineWidth / 2.0, - finishedWidth, height, true, true, stroke, fill); - } else { - Utils.drawRoundedLine(cr, x + lineWidth / 2.0, y + lineWidth / 2.0, - finishedWidth, height, true, true, stroke, fill); - } - - cr.$dispose(); - } - - setProgress(progress) { - if (progress < 0) { - this._hideProgressOverlay(); - } else { - this._progress = Math.min(progress, 1.0); - this._showProgressOverlay(); - } - } - - setUrgent(urgent) { - if (urgent || this._isUrgent !== undefined) - this._source.urgent = urgent; - - if (urgent) - this._isUrgent = urgent; - else - delete this._isUrgent; - } -} - - -// Global icon cache. Used for Unity7 styling. -const iconCacheMap = new Map(); -// Max number of items to store -// We don't expect to ever reach this number, but let's put an hard limit to avoid -// even the remote possibility of the cached items to grow indefinitely. -const MAX_CACHED_ITEMS = 1000; -// When the size exceed it, the oldest 'n' ones are deleted -const BATCH_SIZE_TO_DELETE = 50; -// The icon size used to extract the dominant color -const DOMINANT_COLOR_ICON_SIZE = 64; - -// Compute dominant color frim the app icon. -// The color is cached for efficiency. -class DominantColorExtractor { - constructor(app) { - this._app = app; - } - - /** - * Try to get the pixel buffer for the current icon, if not fail gracefully - */ - _getIconPixBuf() { - let iconTexture = this._app.create_icon_texture(16); - const themeLoader = Docking.DockManager.iconTheme; - - // Unable to load the icon texture, use fallback - if (iconTexture instanceof St.Icon === false) - return null; - - - iconTexture = iconTexture.get_gicon(); - - // Unable to load the icon texture, use fallback - if (!iconTexture) - return null; - - if (iconTexture instanceof Gio.FileIcon) { - // Use GdkPixBuf to load the pixel buffer from the provided file path - return GdkPixbuf.Pixbuf.new_from_file(iconTexture.get_file().get_path()); - } else if (iconTexture instanceof Gio.ThemedIcon) { - // Get the first pixel buffer available in the icon theme - const iconNames = iconTexture.get_names(); - const iconInfo = themeLoader.choose_icon(iconNames, DOMINANT_COLOR_ICON_SIZE, 0); - - if (iconInfo) - return iconInfo.load_icon(); - else - return null; - } - - // Use GdkPixBuf to load the pixel buffer from memory - // iconTexture.load is available unless iconTexture is not an instance of Gio.LoadableIcon - // this means that iconTexture is an instance of Gio.EmblemedIcon, - // which may be converted to a normal icon via iconTexture.get_icon? - const [iconBuffer] = iconTexture.load(DOMINANT_COLOR_ICON_SIZE, null); - return GdkPixbuf.Pixbuf.new_from_stream(iconBuffer, null); - } - - /** - * The backlight color choosing algorithm was mostly ported to javascript from the - * Unity7 C++ source of Canonicals: - * https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp - * so it more or less works the same way. - */ - _getColorPalette() { - if (iconCacheMap.get(this._app.get_id())) { - // We already know the answer - return iconCacheMap.get(this._app.get_id()); - } - - const pixBuf = this._getIconPixBuf(); - if (!pixBuf) - return null; - - let pixels = pixBuf.get_pixels(); - - let total = 0, - rTotal = 0, - gTotal = 0, - bTotal = 0; - - let resampleX = 1; - let resampleY = 1; - - // Resampling of large icons - // We resample icons larger than twice the desired size, as the resampling - // to a size s - // DOMINANT_COLOR_ICON_SIZE < s < 2*DOMINANT_COLOR_ICON_SIZE, - // most of the case exactly DOMINANT_COLOR_ICON_SIZE as the icon size is tipycally - // a multiple of it. - const width = pixBuf.get_width(); - const height = pixBuf.get_height(); - - // Resample - if (height >= 2 * DOMINANT_COLOR_ICON_SIZE) - resampleY = Math.floor(height / DOMINANT_COLOR_ICON_SIZE); - - if (width >= 2 * DOMINANT_COLOR_ICON_SIZE) - resampleX = Math.floor(width / DOMINANT_COLOR_ICON_SIZE); - - if (resampleX !== 1 || resampleY !== 1) - pixels = this._resamplePixels(pixels, resampleX, resampleY); - - // computing the limit outside the for (where it would be repeated at each iteration) - // for performance reasons - const limit = pixels.length; - for (let offset = 0; offset < limit; offset += 4) { - const r = pixels[offset], - g = pixels[offset + 1], - b = pixels[offset + 2], - a = pixels[offset + 3]; - - const saturation = Math.max(r, g, b) - Math.min(r, g, b); - const relevance = 0.1 * 255 * 255 + 0.9 * a * saturation; - - rTotal += r * relevance; - gTotal += g * relevance; - bTotal += b * relevance; - - total += relevance; - } - - total *= 255; - - const r = rTotal / total, - g = gTotal / total, - b = bTotal / total; - - const hsv = Utils.ColorUtils.RGBtoHSV(r * 255, g * 255, b * 255); - - if (hsv.s > 0.15) - hsv.s = 0.65; - hsv.v = 0.90; - - const rgb = Utils.ColorUtils.HSVtoRGB(hsv.h, hsv.s, hsv.v); - - // Cache the result. - const backgroundColor = { - lighter: Utils.ColorUtils.ColorLuminance(rgb.r, rgb.g, rgb.b, 0.2), - original: Utils.ColorUtils.ColorLuminance(rgb.r, rgb.g, rgb.b, 0), - darker: Utils.ColorUtils.ColorLuminance(rgb.r, rgb.g, rgb.b, -0.5), - }; - - if (iconCacheMap.size >= MAX_CACHED_ITEMS) { - // delete oldest cached values (which are in order of insertions) - let ctr = 0; - for (const key of iconCacheMap.keys()) { - if (++ctr > BATCH_SIZE_TO_DELETE) - break; - iconCacheMap.delete(key); - } - } - - iconCacheMap.set(this._app.get_id(), backgroundColor); - - return backgroundColor; - } - - /** - * Downsample large icons before scanning for the backlight color to - * improve performance. - * - * @param pixBuf - * @param pixels - * @param resampleX - * @param resampleY - * - * @returns []; - */ - _resamplePixels(pixels, resampleX, resampleY) { - const resampledPixels = []; - // computing the limit outside the for (where it would be repeated at each iteration) - // for performance reasons - const limit = pixels.length / (resampleX * resampleY) / 4; - for (let i = 0; i < limit; i++) { - const pixel = i * resampleX * resampleY; - - resampledPixels.push(pixels[pixel * 4]); - resampledPixels.push(pixels[pixel * 4 + 1]); - resampledPixels.push(pixels[pixel * 4 + 2]); - resampledPixels.push(pixels[pixel * 4 + 3]); - } - - return resampledPixels; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appIcons.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appIcons.js deleted file mode 100755 index 3c66c8e2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appIcons.js +++ /dev/null @@ -1,1531 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Clutter, - Gio, - GLib, - GObject, - Meta, - Mtk, - Shell, - St, -} from './dependencies/gi.js'; - -import { - AppDisplay, - AppFavorites, - BoxPointer, - Dash, - Main, - PopupMenu, -} from './dependencies/shell/ui.js'; - -import { - ParentalControlsManager, -} from './dependencies/shell/misc.js'; - -import {Config} from './dependencies/shell/misc.js'; - -import { - AppIconIndicators, - DBusMenuUtils, - Docking, - Locations, - Theming, - Utils, - WindowPreview, -} from './imports.js'; - -import {Extension} from './dependencies/shell/extensions/extension.js'; - -// Use __ () and N__() for the extension gettext domain, and reuse -// the shell domain with the default _() and N_() -const {gettext: __, ngettext} = Extension; - -const DBusMenu = await DBusMenuUtils.haveDBusMenu(); - -const tracker = Shell.WindowTracker.get_default(); - -const Labels = Object.freeze({ - ISOLATE_MONITORS: Symbol('isolate-monitors'), - ISOLATE_WORKSPACES: Symbol('isolate-workspaces'), - URGENT_WINDOWS: Symbol('urgent-windows'), -}); - -const clickAction = Object.freeze({ - SKIP: 0, - MINIMIZE: 1, - LAUNCH: 2, - CYCLE_WINDOWS: 3, - MINIMIZE_OR_OVERVIEW: 4, - PREVIEWS: 5, - MINIMIZE_OR_PREVIEWS: 6, - FOCUS_OR_PREVIEWS: 7, - FOCUS_OR_APP_SPREAD: 8, - FOCUS_MINIMIZE_OR_PREVIEWS: 9, - FOCUS_MINIMIZE_OR_APP_SPREAD: 10, - QUIT: 11, -}); - -const scrollAction = Object.freeze({ - DO_NOTHING: 0, - CYCLE_WINDOWS: 1, - SWITCH_WORKSPACE: 2, -}); - -let recentlyClickedAppLoopId = 0; -let recentlyClickedApp = null; -let recentlyClickedAppWindows = null; -let recentlyClickedAppIndex = 0; -let recentlyClickedAppMonitor = -1; - -/** - * Extend AppIcon - * - * - Apply a css class based on the number of windows of each application (#N); - * - Customized indicators for running applications in place of the default "dot" style which is hidden (#N); - * a class of the form "running#N" is applied to the AppWellIcon actor. - * like the original .running one. - * - Add a .focused style to the focused app - * - Customize click actions. - * - Update minimization animation target - * - Update menu if open on windows change - */ -const DockAbstractAppIcon = GObject.registerClass({ - GTypeFlags: GObject.TypeFlags.ABSTRACT, - Properties: { - 'focused': GObject.ParamSpec.boolean( - 'focused', 'focused', 'focused', - GObject.ParamFlags.READWRITE, - false), - 'running': GObject.ParamSpec.boolean( - 'running', 'running', 'running', - GObject.ParamFlags.READWRITE, - false), - 'urgent': GObject.ParamSpec.boolean( - 'urgent', 'urgent', 'urgent', - GObject.ParamFlags.READWRITE, - false), - 'windows-count': GObject.ParamSpec.uint( - 'windows-count', 'windows-count', 'windows-count', - GObject.ParamFlags.READWRITE, - 0, GLib.MAXUINT32, 0), - }, -}, class DockAbstractAppIcon extends Dash.DashIcon { - // settings are required inside. - _init(app, monitorIndex, iconAnimator) { - super._init(app); - - // a prefix is required to avoid conflicting with the parent class variable - this.monitorIndex = monitorIndex; - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - this.iconAnimator = iconAnimator; - this._indicator = new AppIconIndicators.AppIconIndicator(this); - - // Monitor windows-changes instead of app state. - // Keep using the same Id and function callback (that is extended) - if (this._stateChangedId > 0) { - this.app.disconnect(this._stateChangedId); - this._stateChangedId = 0; - } - - this._signalsHandler.add(this.app, 'windows-changed', () => this._updateWindows()); - this._signalsHandler.add(this.app, 'notify::state', () => this._updateRunningState()); - this._signalsHandler.add(global.display, 'window-demands-attention', (_dpy, window) => - this._onWindowDemandsAttention(window)); - this._signalsHandler.add(global.display, 'window-marked-urgent', (_dpy, window) => - this._onWindowDemandsAttention(window)); - - // In Wayland sessions, this signal is needed to track the state of windows dragged - // from one monitor to another. As this is triggered quite often (whenever a new winow - // of any application opened or moved to a different desktop), - // we restrict this signal to the case when 'isolate-monitors' is true, - // and if there are at least 2 monitors. - if (Docking.DockManager.settings.isolateMonitors && - Main.layoutManager.monitors.length > 1) { - this._signalsHandler.addWithLabel(Labels.ISOLATE_MONITORS, - global.display, - 'window-entered-monitor', - this._onWindowEntered.bind(this)); - } - - this.connect('notify::running', () => { - if (this.running) - this.add_style_class_name('running'); - else - this.remove_style_class_name('running'); - }); - - this.connect('notify::focused', () => { - if (this.focused) - this.add_style_class_name('focused'); - else - this.remove_style_class_name('focused'); - }); - - const {notificationsMonitor} = Docking.DockManager.getDefault(); - - this.connect('notify::urgent', () => { - const icon = this.icon._iconBin; - this._signalsHandler.removeWithLabel(Labels.URGENT_WINDOWS); - if (this.urgent) { - if (Docking.DockManager.settings.danceUrgentApplications && - notificationsMonitor.enabled) { - icon.set_pivot_point(0.5, 0.5); - this.iconAnimator.addAnimation(icon, 'wiggle'); - } - if (this.running && !this._urgentWindows.size) { - const urgentWindows = this.getInterestingWindows(); - urgentWindows.forEach(w => (w._manualUrgency = true)); - this._updateUrgentWindows(urgentWindows); - } - } else { - this.iconAnimator.removeAnimation(icon, 'wiggle'); - icon.rotation_angle_z = 0; - this._urgentWindows.forEach(w => delete w._manualUrgency); - this._updateUrgentWindows(); - } - }); - - this._urgentWindows = new Set(); - this._progressOverlayArea = null; - this._progress = 0; - - [ - 'apply-custom-theme', - 'running-indicator-style', - 'show-icons-emblems', - 'show-icons-notifications-counter', - 'application-counter-overrides-notifications', - ].forEach(key => { - this._signalsHandler.add( - Docking.DockManager.settings, - `changed::${key}`, () => { - this._indicator.destroy(); - this._indicator = new AppIconIndicators.AppIconIndicator(this); - } - ); - }); - - this._signalsHandler.add(notificationsMonitor, 'state-changed', () => { - this._indicator.destroy(); - this._indicator = new AppIconIndicators.AppIconIndicator(this); - }); - - this._updateState(); - this._numberOverlay(); - - this._previewMenuManager = null; - this._previewMenu = null; - } - - _onDestroy() { - super._onDestroy(); - - // This is necessary due to an upstream bug - // https://bugzilla.gnome.org/show_bug.cgi?id=757556 - // It can be safely removed once it get solved upstrea. - if (this._menu) - this._menu.close(false); - } - - ownsWindow(window) { - return this.app === tracker.get_window_app(window); - } - - _onWindowEntered(metaScreen, monitorIndex, metaWin) { - if (this.ownsWindow(metaWin)) - this._updateWindows(); - } - - vfunc_scroll_event(scrollEvent) { - const {settings} = Docking.DockManager; - const isEnabled = settings.scrollAction === scrollAction.CYCLE_WINDOWS; - if (!isEnabled) - return Clutter.EVENT_PROPAGATE; - - // We only activate windows of running applications, i.e. we never open new windows - // We check if the app is running, and that the # of windows is > 0 in - // case we use workspace isolation, - if (!this.running) - return Clutter.EVENT_PROPAGATE; - - if (this._optionalScrollCycleWindowsDeadTimeId) { - return Clutter.EVENT_PROPAGATE; - } else { - this._optionalScrollCycleWindowsDeadTimeId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, 250, () => { - this._optionalScrollCycleWindowsDeadTimeId = 0; - }); - } - - let direction = null; - - switch (scrollEvent.direction) { - case Clutter.ScrollDirection.UP: - direction = Meta.MotionDirection.UP; - break; - case Clutter.ScrollDirection.DOWN: - direction = Meta.MotionDirection.DOWN; - break; - case Clutter.ScrollDirection.SMOOTH: { - const [, dy] = Clutter.get_current_event().get_scroll_delta(); - if (dy < 0) - direction = Meta.MotionDirection.UP; - else if (dy > 0) - direction = Meta.MotionDirection.DOWN; - } - break; - } - - if (!Main.overview.visible) { - const reversed = direction === Meta.MotionDirection.UP; - if (this.focused && !this._urgentWindows.size) { - this._cycleThroughWindows(reversed); - } else { - // Activate the first window - const windows = this.getInterestingWindows(); - if (windows.length > 0) { - const [w] = windows; - Main.activateWindow(w); - } - } - } else { - this.app.activate(); - } - return Clutter.EVENT_STOP; - } - - _updateWindows() { - if (this._menu && this._menu.isOpen) - this._menu.update(); - - this._updateState(); - this.updateIconGeometry(); - } - - _updateState() { - this._urgentWindows.clear(); - const interestingWindows = this.getInterestingWindows(); - this.windowsCount = interestingWindows.length; - this._updateRunningState(); - this._updateFocusState(); - this._updateUrgentWindows(interestingWindows); - - if (Docking.DockManager.settings.isolateWorkspaces) { - this._signalsHandler.removeWithLabel(Labels.ISOLATE_WORKSPACES); - interestingWindows.forEach(window => - this._signalsHandler.addWithLabel(Labels.ISOLATE_WORKSPACES, - window, 'workspace-changed', () => this._updateWindows())); - } - } - - _updateRunningState() { - this.running = (this.app.state === Shell.AppState.RUNNING) && this.windowsCount; - } - - _updateFocusState() { - this.focused = tracker.focus_app === this.app && this.running; - } - - _updateUrgentWindows(interestingWindows) { - this._signalsHandler.removeWithLabel(Labels.URGENT_WINDOWS); - this._urgentWindows.clear(); - if (interestingWindows === undefined) - interestingWindows = this.getInterestingWindows(); - interestingWindows.filter(isWindowUrgent).forEach(win => this._addUrgentWindow(win)); - this.urgent = !!this._urgentWindows.size; - } - - _onWindowDemandsAttention(window) { - if (this.ownsWindow(window) && isWindowUrgent(window)) - this._addUrgentWindow(window); - } - - _addUrgentWindow(window) { - if (this._urgentWindows.has(window)) - return; - - if (window._manualUrgency && window.has_focus()) { - delete window._manualUrgency; - return; - } - - this._urgentWindows.add(window); - this.urgent = true; - - const onDemandsAttentionChanged = () => { - if (!isWindowUrgent(window)) - this._updateUrgentWindows(); - }; - - if (window.demandsAttention) { - this._signalsHandler.addWithLabel(Labels.URGENT_WINDOWS, window, - 'notify::demands-attention', () => onDemandsAttentionChanged()); - } - if (window.urgent) { - this._signalsHandler.addWithLabel(Labels.URGENT_WINDOWS, window, - 'notify::urgent', () => onDemandsAttentionChanged()); - } - if (window._manualUrgency) { - this._signalsHandler.addWithLabel(Labels.URGENT_WINDOWS, window, - 'focus', () => { - delete window._manualUrgency; - onDemandsAttentionChanged(); - }); - } - } - - /** - * Update target for minimization animation - */ - updateIconGeometry() { - // If (for unknown reason) the actor is not on the stage the reported size - // and position are random values, which might exceeds the integer range - // resulting in an error when assigned to the a rect. This is a more like - // a workaround to prevent flooding the system with errors. - if (!this.get_stage()) - return; - - const rect = new Mtk.Rectangle(); - - [rect.x, rect.y] = this.get_transformed_position(); - [rect.width, rect.height] = this.get_transformed_size(); - - let windows = this.getWindows(); - if (Docking.DockManager.settings.multiMonitor) { - const {monitorIndex} = this; - windows = windows.filter(w => w.get_monitor() === monitorIndex); - } - windows.forEach(w => w.set_icon_geometry(rect)); - } - - _updateRunningStyle() { - // The logic originally in this function has been moved to - // AppIconIndicatorBase._updateDefaultDot(). However it cannot be removed as - // it called by the parent constructor. - } - - popupMenu() { - this._removeMenuTimeout(); - this.fake_release(); - this._draggable.fakeRelease(); - - if (!this._menu) { - this._menu = new DockAppIconMenu(this); - this._menu.connect('activate-window', (menu, window) => { - if (window) { - Main.activateWindow(window); - } else { - Main.overview.hide(); - Main.panel.closeCalendar(); - } - }); - this._menu.connect('open-state-changed', (menu, isPoppedUp) => { - if (!isPoppedUp) { - this._onMenuPoppedDown(); - } else { - // Setting the max-height is s useful if part of the menu is - // scrollable so the minimum height is smaller than the natural height. - const monitorIndex = Main.layoutManager.findIndexForActor(this); - const workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex); - const position = Utils.getPosition(); - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const isHorizontal = position === St.Side.TOP || position === St.Side.BOTTOM; - // If horizontal also remove the height of the dash - const {dockFixed: fixedDock} = Docking.DockManager.settings; - const additionalMargin = isHorizontal && !fixedDock ? Main.overview.dash.height : 0; - const verticalMargins = this._menu.actor.margin_top + this._menu.actor.margin_bottom; - const maxMenuHeight = workArea.height - additionalMargin - verticalMargins; - // Also set a max width to the menu, so long labels (long windows title) get truncated - this._menu.actor.style = 'max-width: 400px; ' + - `max-height: ${Math.round(maxMenuHeight / scaleFactor)}px;`; - } - }); - const id = Main.overview.connect('hiding', () => { - this._menu.close(); - }); - this._menu.actor.connect('destroy', () => { - Main.overview.disconnect(id); - }); - - this._menuManager.addMenu(this._menu); - } - - this.emit('menu-state-changed', true); - - this.set_hover(true); - this._menu.popup(); - this._menuManager.ignoreRelease(); - this.emit('sync-tooltip'); - - return false; - } - - activate(button) { - const event = Clutter.get_current_event(); - let modifiers = event ? event.get_state() : 0; - - // Only consider SHIFT and CONTROL as modifiers (exclude SUPER, CAPS-LOCK, etc.) - modifiers &= Clutter.ModifierType.SHIFT_MASK | Clutter.ModifierType.CONTROL_MASK; - - // We don't change the CTRL-click behaviour: in such case we just chain - // up the parent method and return. - if (modifiers & Clutter.ModifierType.CONTROL_MASK) { - // Keep default behaviour: launch new window - // By calling the parent method I make it compatible - // with other extensions tweaking ctrl + click - super.activate(button); - return; - } - - // We check what type of click we have and if the modifier SHIFT is - // being used. We then define what buttonAction should be for this - // event. - let buttonAction = 0; - const {settings} = Docking.DockManager; - if (button && button === 2) { - if (modifiers & Clutter.ModifierType.SHIFT_MASK) - buttonAction = settings.shiftMiddleClickAction; - else - buttonAction = settings.middleClickAction; - } else if (button && button === 1) { - if (modifiers & Clutter.ModifierType.SHIFT_MASK) - buttonAction = settings.shiftClickAction; - else - buttonAction = settings.clickAction; - } - - switch (buttonAction) { - case clickAction.FOCUS_OR_APP_SPREAD: - if (!Docking.DockManager.getDefault().appSpread.supported) - buttonAction = clickAction.FOCUS_OR_PREVIEWS; - break; - - case clickAction.FOCUS_MINIMIZE_OR_APP_SPREAD: - if (!Docking.DockManager.getDefault().appSpread.supported) - buttonAction = clickAction.FOCUS_MINIMIZE_OR_PREVIEWS; - break; - } - - // We check if the app is running, and that the # of windows is > 0 in - // case we use workspace isolation. - const windows = this.getInterestingWindows(); - - // Some action modes (e.g. MINIMIZE_OR_OVERVIEW) require overview to remain open - // This variable keeps track of this - let shouldHideOverview = true; - - // We customize the action only when the application is already running - if (this.running) { - const hasUrgentWindows = !!this._urgentWindows.size; - const singleOrUrgentWindows = windows.length === 1 || hasUrgentWindows; - switch (buttonAction) { - case clickAction.MINIMIZE: - // In overview just activate the app, unless the acion is explicitely - // requested with a keyboard modifier - if (!Main.overview.visible || modifiers) { - // If we have button=2 or a modifier, allow minimization even if - // the app is not focused - if (this.focused && !hasUrgentWindows || button === 2 || - modifiers & Clutter.ModifierType.SHIFT_MASK) { - // minimize all windows on double click and always in - // the case of primary click without additional modifiers - let clickCount = 0; - if (Clutter.EventType.CLUTTER_BUTTON_PRESS) - clickCount = event.get_click_count(); - const allWindows = (button === 1 && !modifiers) || clickCount > 1; - this._minimizeWindow(allWindows); - } else { - this._activateAllWindows(); - } - } else { - const [w] = windows; - Main.activateWindow(w); - } - break; - - case clickAction.MINIMIZE_OR_OVERVIEW: - // When a single window is present, toggle minimization - // If only one windows is present toggle minimization, but - // only when triggered with the simple click action - // (no modifiers, no middle click). - if (singleOrUrgentWindows && !modifiers && button === 1) { - const [w] = windows; - if (this.focused) { - if (buttonAction !== clickAction.FOCUS_OR_APP_SPREAD) { - // Window is raised, minimize it - this._minimizeWindow(w); - } - } else { - // Window is minimized, raise it - Main.activateWindow(w); - } - // Launch overview when multiple windows are present - // TODO: only show current app windows when gnome shell API will allow it - } else { - shouldHideOverview = false; - Main.overview.toggle(); - } - break; - - case clickAction.CYCLE_WINDOWS: - if (!Main.overview.visible) { - if (this.focused && !hasUrgentWindows) { - this._cycleThroughWindows(); - } else { - // Activate the first window - const [w] = windows; - Main.activateWindow(w); - } - } else { - this.app.activate(); - } - break; - - case clickAction.FOCUS_OR_PREVIEWS: - if (this.focused && !hasUrgentWindows && - (windows.length > 1 || modifiers || button !== 1)) { - this._windowPreviews(); - } else { - // Activate the first window - const [w] = windows; - Main.activateWindow(w); - } - break; - - case clickAction.FOCUS_MINIMIZE_OR_PREVIEWS: - if (this.focused && !hasUrgentWindows) { - if (windows.length > 1 || modifiers || button !== 1) - this._windowPreviews(); - else if (!Main.overview.visible) - this._minimizeWindow(); - } else { - // Activate the first window - const [w] = windows; - Main.activateWindow(w); - } - break; - - case clickAction.LAUNCH: - this.launchNewWindow(); - break; - - case clickAction.PREVIEWS: - if (!Main.overview.visible) { - // If only one windows is present just switch to it, - // but only when trigggered with the simple click action - // (no modifiers, no middle click). - if (singleOrUrgentWindows && !modifiers && button === 1) { - const [w] = windows; - Main.activateWindow(w); - } else { - this._windowPreviews(); - } - } else { - this.app.activate(); - } - break; - - case clickAction.MINIMIZE_OR_PREVIEWS: - // When a single window is present, toggle minimization - // If only one windows is present toggle minimization, but only - // when trigggered with the imple click action (no modifiers, - // no middle click). - if (!Main.overview.visible) { - if (singleOrUrgentWindows && !modifiers && button === 1) { - const [w] = windows; - if (this.focused) { - // Window is raised, minimize it - this._minimizeWindow(w); - } else { - // Window is minimized, raise it - Main.activateWindow(w); - } - } else { - // Launch previews when multiple windows are present - this._windowPreviews(); - } - } else { - this.app.activate(); - } - break; - - case clickAction.FOCUS_OR_APP_SPREAD: - if (this.focused && !singleOrUrgentWindows && !modifiers && button === 1) { - shouldHideOverview = false; - Docking.DockManager.getDefault().appSpread.toggle(this.app); - } else { - // Activate the first window - Main.activateWindow(windows[0]); - } - break; - - case clickAction.FOCUS_MINIMIZE_OR_APP_SPREAD: - if (this.focused && !singleOrUrgentWindows && !modifiers && button === 1) { - shouldHideOverview = false; - Docking.DockManager.getDefault().appSpread.toggle(this.app); - } else if (!this.focused) { - // Activate the first window - Main.activateWindow(windows[0]); - } else { - this._minimizeWindow(); - } - break; - - case clickAction.QUIT: - this.closeAllWindows(); - break; - - case clickAction.SKIP: - Main.activateWindow(windows[0]); - break; - } - } else { - this.launchNewWindow(); - } - - // Hide overview except when action mode requires it - if (shouldHideOverview) - Main.overview.hide(); - } - - shouldShowTooltip() { - return this.hover && (!this._menu || !this._menu.isOpen) && - (!this._previewMenu || !this._previewMenu.isOpen) && - !Docking.DockManager.settings.hideTooltip; - } - - _windowPreviews() { - if (!this._previewMenu) { - this._previewMenuManager = new PopupMenu.PopupMenuManager(this); - - this._previewMenu = new WindowPreview.WindowPreviewMenu(this); - - this._previewMenuManager.addMenu(this._previewMenu); - - this._previewMenu.connect('open-state-changed', (menu, isPoppedUp) => { - if (!isPoppedUp) - this._onMenuPoppedDown(); - }); - const id = Main.overview.connect('hiding', () => { - this._previewMenu.close(); - }); - this._previewMenu.actor.connect('destroy', () => { - Main.overview.disconnect(id); - }); - } - - this.emit('menu-state-changed', !this._previewMenu.isOpen); - - if (this._previewMenu.isOpen) - this._previewMenu.close(); - else - this._previewMenu.popup(); - - return false; - } - - // Try to do the right thing when attempting to launch a new window of an app. In - // particular, if the application doens't allow to launch a new window, activate - // the existing window instead. - launchNewWindow() { - if (this.app.state === Shell.AppState.RUNNING && - this.app.can_open_new_window()) { - this.animateLaunch(); - this.app.open_new_window(-1); - } else { - // Try to manually activate the first window. Otherwise, when the - // app is activated by switching to a different workspace, a launch - // spinning icon is shown and disappers only after a timeout. - const windows = this.getWindows(); - if (windows.length > 0) { - Main.activateWindow(windows[0]); - } else { - this.app.activate(); - this.animateLaunch(); - } - } - } - - _numberOverlay() { - // Add label for a Hot-Key visual aid - this._numberOverlayLabel = new St.Label(); - this._numberOverlayBin = new St.Bin({ - child: this._numberOverlayLabel, - x_align: Clutter.ActorAlign.START, - y_align: Clutter.ActorAlign.START, - x_expand: true, y_expand: true, - }); - this._numberOverlayLabel.add_style_class_name('number-overlay'); - this._numberOverlayOrder = -1; - this._numberOverlayBin.hide(); - - this._iconContainer.add_child(this._numberOverlayBin); - } - - updateNumberOverlay() { - // We apply an overall scale factor that might come from a HiDPI monitor. - // Clutter dimensions are in physical pixels, but CSS measures are in logical - // pixels, so make sure to consider the scale. - const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - // Set the font size to something smaller than the whole icon so it is - // still visible. The border radius is large to make the shape circular - const [minWidth_, natWidth] = this._iconContainer.get_preferred_width(-1); - const fontSize = Math.round(Math.max(12, 0.3 * natWidth) / scaleFactor); - const size = Math.round(fontSize * 1.2); - this._numberOverlayLabel.set_style( - `font-size: ${fontSize}px;` + - `border-radius: ${this.icon.iconSize}px;` + - `width: ${size}px; height: ${size}px;` - ); - } - - setNumberOverlay(number) { - this._numberOverlayOrder = number; - this._numberOverlayLabel.set_text(number.toString()); - } - - toggleNumberOverlay(activate) { - if (activate && this._numberOverlayOrder > -1) { - this.updateNumberOverlay(); - this._numberOverlayBin.show(); - } else { - this._numberOverlayBin.hide(); - } - } - - _minimizeWindow(param) { - // Param true make all app windows minimize - const windows = this.getInterestingWindows(); - const currentWorkspace = global.workspace_manager.get_active_workspace(); - for (let i = 0; i < windows.length; i++) { - const w = windows[i]; - if (w.get_workspace() === currentWorkspace && w.showing_on_its_workspace()) { - w.minimize(); - // Just minimize one window. By specification it should be the - // focused window on the current workspace. - if (!param) - break; - } - } - } - - // By default only non minimized windows are activated. - // This activates all windows in the current workspace. - _activateAllWindows() { - // First activate first window so workspace is switched if needed. - // We don't do this if isolation is on! - if (!Docking.DockManager.settings.isolateWorkspaces && - !Docking.DockManager.settings.isolateMonitors) { - if (!this.running) - this.animateLaunch(); - this.app.activate(); - } - - // then activate all other app windows in the current workspace - const windows = this.getInterestingWindows(); - const activeWorkspace = global.workspace_manager.get_active_workspace_index(); - - if (windows.length <= 0) - return; - - for (let i = windows.length - 1; i >= 0; i--) { - if (windows[i].get_workspace()?.index() === activeWorkspace) - Main.activateWindow(windows[i]); - } - } - - // This closes all windows of the app. - closeAllWindows() { - const windows = this.getInterestingWindows(); - const time = global.get_current_time(); - windows.forEach(w => w.delete(time)); - } - - _cycleThroughWindows(reversed) { - // Store for a little amount of time last clicked app and its windows - // since the order changes upon window interaction - const MEMORY_TIME = 3000; - - const appWindows = this.getInterestingWindows(); - - if (appWindows.length < 1) - return; - - if (recentlyClickedAppLoopId > 0) - GLib.source_remove(recentlyClickedAppLoopId); - recentlyClickedAppLoopId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, MEMORY_TIME, this._resetRecentlyClickedApp); - - // If there isn't already a list of windows for the current app, - // or the stored list is outdated, use the current windows list. - const monitorIsolation = Docking.DockManager.settings.isolateMonitors; - if (!recentlyClickedApp || - recentlyClickedApp.get_id() !== this.app.get_id() || - recentlyClickedAppWindows.length !== appWindows.length || - (recentlyClickedAppMonitor !== this.monitorIndex && monitorIsolation)) { - recentlyClickedApp = this.app; - recentlyClickedAppWindows = appWindows; - recentlyClickedAppMonitor = this.monitorIndex; - recentlyClickedAppIndex = 0; - } - - if (reversed) { - recentlyClickedAppIndex--; - if (recentlyClickedAppIndex < 0) - recentlyClickedAppIndex = recentlyClickedAppWindows.length - 1; - } else { - recentlyClickedAppIndex++; - } - const index = recentlyClickedAppIndex % recentlyClickedAppWindows.length; - const window = recentlyClickedAppWindows[index]; - - Main.activateWindow(window); - } - - _resetRecentlyClickedApp() { - if (recentlyClickedAppLoopId > 0) - GLib.source_remove(recentlyClickedAppLoopId); - recentlyClickedAppLoopId = 0; - recentlyClickedApp = null; - recentlyClickedAppWindows = null; - recentlyClickedAppIndex = 0; - recentlyClickedAppMonitor = -1; - - return false; - } - - getWindows() { - return this.app.get_windows(); - } - - // Filter out unnecessary windows, for instance - // nautilus desktop window. - getInterestingWindows() { - const interestingWindows = getInterestingWindows(this.getWindows(), - this.monitorIndex); - - if (!this._urgentWindows.size) - return interestingWindows; - - return [...new Set([...this._urgentWindows, ...interestingWindows])]; - } -}); - -const DockAppIcon = GObject.registerClass({ -}, class DockAppIcon extends DockAbstractAppIcon { - _init(app, monitorIndex, iconAnimator) { - super._init(app, monitorIndex, iconAnimator); - - this._signalsHandler.add(tracker, 'notify::focus-app', () => this._updateFocusState()); - } -}); - -const DockLocationAppIcon = GObject.registerClass({ -}, class DockLocationAppIcon extends DockAbstractAppIcon { - _init(app, monitorIndex, iconAnimator) { - if (!(app.appInfo instanceof Locations.LocationAppInfo)) - throw new Error('Provided application %s is not a Location'.format(app)); - - super._init(app, monitorIndex, iconAnimator); - - if (Docking.DockManager.settings.isolateLocations) { - this._signalsHandler.add(tracker, 'notify::focus-app', () => this._updateFocusState()); - } else { - this._signalsHandler.add(global.display, 'notify::focus-window', - () => this._updateFocusState()); - } - - this._signalsHandler.add(this.app, 'notify::icon', () => this.icon.update()); - } - - get location() { - return this.app.location; - } - - _updateFocusState() { - if (Docking.DockManager.settings.isolateLocations) { - super._updateFocusState(); - return; - } - - this.focused = this.app.isFocused && this.running; - } -}); - -/** - * @param app - * @param monitorIndex - * @param iconAnimator - */ -export function makeAppIcon(app, monitorIndex, iconAnimator) { - if (app.appInfo instanceof Locations.LocationAppInfo) - return new DockLocationAppIcon(app, monitorIndex, iconAnimator); - - return new DockAppIcon(app, monitorIndex, iconAnimator); -} - -/** - * DockAppIconMenu - * - * - set popup arrow side based on dash orientation - * - Add close windows option based on quitfromdash extension - * (https://github.com/deuill/shell-extension-quitfromdash) - * - Add open windows thumbnails instead of list - * - update menu when application windows change - */ -const DockAppIconMenu = class DockAppIconMenu extends PopupMenu.PopupMenu { - constructor(source) { - super(source, 0.5, Utils.getPosition()); - - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - - // We want to keep the item hovered while the menu is up - this.blockSourceEvents = true; - - this._source = source; - this._parentalControlsManager = ParentalControlsManager.getDefault(); - - this.actor.add_style_class_name('app-menu'); - this.actor.add_style_class_name('dock-app-menu'); - - // Chain our visibility and lifecycle to that of the source - this._signalsHandler.add(source, 'notify::mapped', () => { - if (!source.mapped) - this.close(); - }); - source.connect('destroy', () => this.destroy()); - - Main.uiGroup.add_child(this.actor); - - const {remoteModel} = Docking.DockManager.getDefault(); - const remoteModelApp = remoteModel?.lookupById(this._source?.app?.id); - if (remoteModelApp && DBusMenu) { - const [onQuicklist, onDynamicSection] = Utils.splitHandler((sender, - {quicklist}, dynamicSection) => { - dynamicSection.removeAll(); - if (quicklist) { - quicklist.get_children().forEach(remoteItem => - dynamicSection.addMenuItem( - DBusMenuUtils.makePopupMenuItem(remoteItem, false))); - } - }); - - this._signalsHandler.add([ - remoteModelApp, - 'quicklist-changed', - onQuicklist, - ], [ - this, - 'dynamic-section-changed', - onDynamicSection, - ]); - } - } - - _appendSeparator() { - this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - } - - _appendMenuItem(labelText) { - const item = new PopupMenu.PopupMenuItem(labelText); - this.addMenuItem(item); - return item; - } - - popup(_activatingButton) { - this._rebuildMenu(); - this.open(BoxPointer.PopupAnimation.FULL); - } - - _rebuildMenu() { - this.removeAll(); - - if (Docking.DockManager.settings.showWindowsPreview) { - // Display the app windows menu items and the separator between windows - // of the current desktop and other windows. - const windows = this._source.getInterestingWindows(); - - this._allWindowsMenuItem = new PopupMenu.PopupSubMenuMenuItem(__('All Windows'), false); - if (this._allWindowsMenuItem.menu?.actor) - this._allWindowsMenuItem.menu.actor.overlayScrollbars = true; - this._allWindowsMenuItem.hide(); - if (windows.length > 0) - this.addMenuItem(this._allWindowsMenuItem); - } else { - const windows = this._source.getInterestingWindows(); - - if (windows.length > 0) { - this.addMenuItem( - /* Translators: This is the heading of a list of open windows */ - new PopupMenu.PopupSeparatorMenuItem(_('Open Windows'))); - } - - windows.forEach(window => { - const title = window.title - ? window.title : this._source.app.get_name(); - const item = this._appendMenuItem(title); - item.connect('activate', () => { - this.emit('activate-window', window); - }); - }); - } - - if (!this._source.app.is_window_backed()) { - this._appendSeparator(); - - const appInfo = this._source.app.get_app_info(); - const actions = appInfo.list_actions(); - if (this._source.app.can_open_new_window() && - actions.indexOf('new-window') === -1) { - this._newWindowMenuItem = this._appendMenuItem(_('New Window')); - this._newWindowMenuItem.connect('activate', () => { - if (this._source.app.state === Shell.AppState.STOPPED) - this._source.animateLaunch(); - - this._source.app.open_new_window(-1); - this.emit('activate-window', null); - }); - this._appendSeparator(); - } - - if (Docking.DockManager.getDefault().discreteGpuAvailable && - this._source.app.state === Shell.AppState.STOPPED) { - const appPrefersNonDefaultGPU = appInfo.get_boolean('PrefersNonDefaultGPU'); - const gpuPref = appPrefersNonDefaultGPU - ? Shell.AppLaunchGpu.DEFAULT - : Shell.AppLaunchGpu.DISCRETE; - this._onGpuMenuItem = this._appendMenuItem(appPrefersNonDefaultGPU - ? _('Launch using Integrated Graphics Card') - : _('Launch using Discrete Graphics Card')); - this._onGpuMenuItem.connect('activate', () => { - this._source.animateLaunch(); - this._source.app.launch(0, -1, gpuPref); - this.emit('activate-window', null); - }); - } - - for (let i = 0; i < actions.length; i++) { - const action = actions[i]; - const item = this._appendMenuItem(appInfo.get_action_name(action)); - item.sensitive = !appInfo.busy; - item.connect('activate', (emitter, event) => { - this._source.app.launch_action(action, event.get_time(), -1); - this.emit('activate-window', null); - }); - } - - const canFavorite = global.settings.is_writable('favorite-apps') && - (this._source instanceof DockAppIcon) && - this._parentalControlsManager.shouldShowApp(this._source.app.app_info); - - if (canFavorite) { - this._appendSeparator(); - - const isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id()); - const [majorVersion] = Config.PACKAGE_VERSION.split('.'); - - if (isFavorite) { - const label = majorVersion >= 42 ? _('Unpin') - : _('Remove from Favorites'); - const item = this._appendMenuItem(label); - item.connect('activate', () => { - const favs = AppFavorites.getAppFavorites(); - favs.removeFavorite(this._source.app.get_id()); - }); - } else { - const label = majorVersion >= 42 ? _('Pin to Dash') - : _('Add to Favorites'); - const item = this._appendMenuItem(label); - item.connect('activate', () => { - const favs = AppFavorites.getAppFavorites(); - favs.addFavorite(this._source.app.get_id()); - }); - } - } - - if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop') && - (this._source instanceof DockAppIcon)) { - this._appendSeparator(); - const item = this._appendMenuItem(_('App Details')); - item.connect('activate', () => { - const id = this._source.app.get_id(); - const args = GLib.Variant.new('(ss)', [id, '']); - Gio.DBus.get(Gio.BusType.SESSION, null, - (o, res) => { - const bus = Gio.DBus.get_finish(res); - bus.call('org.gnome.Software', - '/org/gnome/Software', - 'org.gtk.Actions', 'Activate', - GLib.Variant.new('(sava{sv})', - ['details', [args], null]), - null, 0, -1, null, null); - Main.overview.hide(); - }); - }); - } - } - - // dynamic menu - const items = this._getMenuItems(); - let i = items.length; - if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) - i -= 2; - - if (global.settings.is_writable('favorite-apps')) - i -= 2; - - if (i < 0) - i = 0; - - const dynamicSection = new PopupMenu.PopupMenuSection(); - this.addMenuItem(dynamicSection, i); - this.emit('dynamic-section-changed', dynamicSection); - - // quit menu - this._appendSeparator(); - this._quitMenuItem = this._appendMenuItem(_('Quit')); - this._quitMenuItem.connect('activate', () => this._source.closeAllWindows()); - - this.update(); - } - - // update menu content when application windows change. This is desirable as actions - // acting on windows (closing) are performed while the menu is shown. - update() { - // update, show or hide the quit menu - if (this._source.windowsCount > 0) { - if (this._source.windowsCount === 1) { - this._quitMenuItem.label.set_text(_('Quit')); - } else { - this._quitMenuItem.label.set_text(ngettext( - 'Quit %d Window', 'Quit %d Windows', this._source.windowsCount).format( - this._source.windowsCount)); - } - - this._quitMenuItem.actor.show(); - } else { - this._quitMenuItem.actor.hide(); - } - - if (Docking.DockManager.settings.showWindowsPreview) { - const windows = this._source.getInterestingWindows(); - - // update, show, or hide the allWindows menu - // Check if there are new windows not already displayed. In such case, - // repopulate the allWindows menu. Windows removal is already handled - // by each preview being connected to the destroy signal - const oldWindows = this._allWindowsMenuItem.menu._getMenuItems().map(item => { - return item._window; - }); - - const newWindows = windows.filter(w => - oldWindows.indexOf(w) < 0); - if (newWindows.length > 0) { - this._populateAllWindowMenu(windows); - - // Try to set the width to that of the submenu. - // TODO: can't get the actual size, getting a bit less. - // Temporary workaround: add 15px to compensate - this._allWindowsMenuItem.width = this._allWindowsMenuItem.menu.actor.width + 15; - } - - // The menu is created hidden and never hidded after being shown. - // Instead, a signal connected to its items destroy will set is - // insensitive if no more windows preview are shown. - if (windows.length > 0) { - this._allWindowsMenuItem.show(); - this._allWindowsMenuItem.setSensitive(true); - - if (Docking.DockManager.settings.defaultWindowsPreviewToOpen) - this._allWindowsMenuItem.menu.open(); - } - } - - // Update separators - this._getMenuItems().forEach(item => { - if ('label' in item) - this._updateSeparatorVisibility(item); - }); - } - - _populateAllWindowMenu(windows) { - this._allWindowsMenuItem.menu.removeAll(); - - if (windows.length > 0) { - const activeWorkspace = global.workspace_manager.get_active_workspace(); - let separatorShown = windows[0].get_workspace() !== activeWorkspace; - - for (let i = 0; i < windows.length; i++) { - const window = windows[i]; - if (!separatorShown && window.get_workspace() !== activeWorkspace) { - this._allWindowsMenuItem.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - separatorShown = true; - } - - const item = new WindowPreview.WindowPreviewMenuItem(window, - St.Side.LEFT); - this._allWindowsMenuItem.menu.addMenuItem(item); - item.connect('activate', () => { - this.emit('activate-window', window); - }); - - // This is to achieve a more gracefull transition when the last windows is closed. - item.connect('destroy', () => { - // It's still counting the item just going to be destroyed - if (this._allWindowsMenuItem.menu._getMenuItems().length === 1) - this._allWindowsMenuItem.setSensitive(false); - }); - } - } - } -}; - -/** - * @param w - */ -function isWindowUrgent(w) { - return w.urgent || w.demandsAttention || w._manualUrgency; -} - -/** - * Filter out unnecessary windows, for instance - * nautilus desktop window. - * - * @param windows - * @param monitorIndex - */ -export function getInterestingWindows(windows, monitorIndex) { - const {settings} = Docking.DockManager; - - // When using workspace isolation, we filter out windows - // that are neither in the current workspace nor marked urgent - if (settings.isolateWorkspaces) { - const showUrgent = settings.workspaceAgnosticUrgentWindows; - const activeWorkspace = global.workspace_manager.get_active_workspace(); - windows = windows.filter(w => { - const inWorkspace = w.get_workspace() === activeWorkspace; - return inWorkspace || (showUrgent && isWindowUrgent(w)); - }); - } - - if (settings.isolateMonitors && monitorIndex >= 0) { - windows = windows.filter(w => { - return w.get_monitor() === monitorIndex; - }); - } - - return windows.filter(w => !w.skipTaskbar); -} - -/** - * A ShowAppsIcon improved class. - * - * - set label position based on dash orientation - * Note: we are am reusing most machinery of the appIcon class. - * - implement a popupMenu based on the AppIcon code - * Note: we are reusing most machinery of the appIcon class) - * - */ - -export const DockShowAppsIcon = GObject.registerClass({ - Signals: { - 'menu-state-changed': {param_types: [GObject.TYPE_BOOLEAN]}, - 'sync-tooltip': {}, - }, -} -, class DockShowAppsIcon extends Dash.ShowAppsIcon { - _init(position) { - super._init(); - - // Re-use appIcon methods - const {prototype: appIconPrototype} = AppDisplay.AppIcon; - this.toggleButton.y_expand = false; - this.toggleButton.connect('popup-menu', () => - appIconPrototype._onKeyboardPopupMenu.call(this)); - this.toggleButton.connect('clicked', () => - this._removeMenuTimeout()); - - this.reactive = true; - this.toggleButton.popupMenu = (...args) => - this.popupMenu(...args); - this.toggleButton._setPopupTimeout = (...args) => - this._setPopupTimeout(...args); - this.toggleButton._removeMenuTimeout = (...args) => - this._removeMenuTimeout(...args); - - this.label?.add_style_class_name(Theming.PositionStyleClass[position]); - if (Docking.DockManager.settings.customThemeShrink) - this.label?.add_style_class_name('shrink'); - - this._menu = null; - this._menuManager = new PopupMenu.PopupMenuManager(this); - this._menuTimeoutId = 0; - } - - _createIcon(size) { - this._iconActor = super._createIcon(size); - this._iconActor.fallbackIconName = this._iconActor.iconName; - this._iconActor.fallbackGicon = this._iconActor.gicon; - this._iconActor.iconName = `view-app-grid-${Main.sessionMode.currentMode}-symbolic`; - return this._iconActor; - } - - vfunc_leave_event(...args) { - return AppDisplay.AppIcon.prototype.vfunc_leave_event.call( - this.toggleButton, ...args); - } - - vfunc_button_press_event(...args) { - return AppDisplay.AppIcon.prototype.vfunc_button_press_event.call( - this.toggleButton, ...args); - } - - vfunc_touch_event(...args) { - return AppDisplay.AppIcon.prototype.vfunc_touch_event.call( - this.toggleButton, ...args); - } - - showLabel(...args) { - itemShowLabel.call(this, ...args); - } - - setForcedHighlight(...args) { - AppDisplay.AppIcon.prototype.setForcedHighlight.call(this, ...args); - } - - _onMenuPoppedDown(...args) { - AppDisplay.AppIcon.prototype._onMenuPoppedDown.call(this, ...args); - } - - _setPopupTimeout(...args) { - AppDisplay.AppIcon.prototype._setPopupTimeout.call(this, ...args); - } - - _removeMenuTimeout(...args) { - AppDisplay.AppIcon.prototype._removeMenuTimeout.call(this, ...args); - } - - popupMenu() { - this._removeMenuTimeout(); - this.toggleButton.fake_release(); - - if (!this._menu) { - this._menu = new DockShowAppsIconMenu(this); - this._menu.connect('open-state-changed', (menu, isPoppedUp) => { - if (!isPoppedUp) - this._onMenuPoppedDown(); - }); - const id = Main.overview.connect('hiding', () => { - this._menu.close(); - }); - this._menu.actor.connect('destroy', () => { - Main.overview.disconnect(id); - }); - this._menuManager.addMenu(this._menu); - } - - this.emit('menu-state-changed', true); - - this.toggleButton.set_hover(true); - this._menu.popup(); - this._menuManager.ignoreRelease(); - this.emit('sync-tooltip'); - - return false; - } -}); - - -/** - * A menu for the showAppsIcon - */ -class DockShowAppsIconMenu extends DockAppIconMenu { - _rebuildMenu() { - this.removeAll(); - - /* Translators: %s is "Settings", which is automatically translated. You - can also translate the full message if this fits better your language. */ - const name = __('Dash to Dock %s').format(_('Settings')); - const item = this._appendMenuItem(name); - - item.connect('activate', () => - Docking.DockManager.extension.openPreferences()); - } -} - -/** - * This function is used for both DockShowAppsIcon and DockDashItemContainer - */ -export function itemShowLabel() { - /* eslint-disable no-invalid-this */ - // Check if the label is still present at all. When switching workpaces, the - // item might have been destroyed in between. - if (!this._labelText || !this.label.get_stage()) - return; - - this.label.set_text(this._labelText); - this.label.opacity = 0; - this.label.show(); - - const [stageX, stageY] = this.get_transformed_position(); - const node = this.label.get_theme_node(); - - const itemWidth = this.allocation.x2 - this.allocation.x1; - const itemHeight = this.allocation.y2 - this.allocation.y1; - - const labelWidth = this.label.get_width(); - const labelHeight = this.label.get_height(); - - let x, y, xOffset, yOffset; - - const position = Utils.getPosition(); - const labelOffset = node.get_length('-x-offset'); - - switch (position) { - case St.Side.LEFT: - yOffset = Math.floor((itemHeight - labelHeight) / 2); - y = stageY + yOffset; - xOffset = labelOffset; - x = stageX + this.get_width() + xOffset; - break; - case St.Side.RIGHT: - yOffset = Math.floor((itemHeight - labelHeight) / 2); - y = stageY + yOffset; - xOffset = labelOffset; - x = Math.round(stageX) - labelWidth - xOffset; - break; - case St.Side.TOP: - y = stageY + labelOffset + itemHeight; - xOffset = Math.floor((itemWidth - labelWidth) / 2); - x = stageX + xOffset; - break; - case St.Side.BOTTOM: - yOffset = labelOffset; - y = stageY - labelHeight - yOffset; - xOffset = Math.floor((itemWidth - labelWidth) / 2); - x = stageX + xOffset; - break; - } - - // keep the label inside the screen border - // Only needed fot the x coordinate. - - // Leave a few pixel gap - const gap = 5; - const monitor = Main.layoutManager.findMonitorForActor(this); - if (x - monitor.x < gap) - x += monitor.x - x + labelOffset; - else if (x + labelWidth > monitor.x + monitor.width - gap) - x -= x + labelWidth - (monitor.x + monitor.width) + gap; - - this.label.remove_all_transitions(); - this.label.set_position(x, y); - this.label.ease({ - opacity: 255, - duration: Dash.DASH_ITEM_LABEL_SHOW_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - /* eslint-enable no-invalid-this */ -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appSpread.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appSpread.js deleted file mode 100755 index 6a1dedfe..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/appSpread.js +++ /dev/null @@ -1,210 +0,0 @@ -import {Atk, Clutter} from './dependencies/gi.js'; - -import { - Main, - SearchController, - Workspace, - WorkspaceThumbnail, -} from './dependencies/shell/ui.js'; - -import {Utils} from './imports.js'; - -export class AppSpread { - constructor() { - this.app = null; - this.supported = true; - this.windows = []; - - // fail early and do nothing, if mandatory gnome shell functions are missing - if (Main.overview.isDummy || - !Workspace?.Workspace?.prototype._isOverviewWindow || - !WorkspaceThumbnail?.WorkspaceThumbnail?.prototype._isOverviewWindow) { - log('Dash to dock: Unable to temporarily replace shell functions ' + - 'for app spread - using previews instead'); - this.supported = false; - return; - } - - this._signalHandlers = new Utils.GlobalSignalsHandler(); - this._methodInjections = new Utils.InjectionsHandler(); - this._vfuncInjections = new Utils.VFuncInjectionsHandler(); - } - - get isInAppSpread() { - return !!this.app; - } - - destroy() { - if (!this.supported) - return; - this._hideAppSpread(); - this._signalHandlers.destroy(); - this._methodInjections.destroy(); - this._vfuncInjections.destroy(); - } - - toggle(app) { - const newApp = this.app !== app; - if (this.app) - Main.overview.hide(); // also triggers hook 'hidden' - - if (app && newApp) - this._showAppSpread(app); - } - - _updateWindows() { - this.windows = this.app.get_windows(); - } - - _restoreDefaultWindows() { - const {workspaceManager} = global; - - for (let i = 0; i < workspaceManager.nWorkspaces; i++) { - const metaWorkspace = workspaceManager.get_workspace_by_index(i); - metaWorkspace.list_windows().forEach(w => metaWorkspace.emit('window-added', w)); - } - } - - _filterWindows() { - const {workspaceManager} = global; - - for (let i = 0; i < workspaceManager.nWorkspaces; i++) { - const metaWorkspace = workspaceManager.get_workspace_by_index(i); - metaWorkspace.list_windows().filter(w => !this.windows.includes(w)).forEach( - w => metaWorkspace.emit('window-removed', w)); - } - } - - _restoreDefaultOverview() { - this._hideAppSpread(); - this._restoreDefaultWindows(); - } - - _showAppSpread(app) { - if (this.isInAppSpread) - return; - - // Checked in overview "hide" event handler _hideAppSpread - this.app = app; - this._updateWindows(); - - // we need to hook into overview 'hidden' like this, in case app spread - // overview is hidden by choosing another app it should then do its - // cleanup too - this._signalHandlers.add(Main.overview, 'hidden', () => this._hideAppSpread()); - - const appSpread = this; - this._methodInjections.add([ - // Filter workspaces to only show current app windows - Workspace.Workspace.prototype, '_isOverviewWindow', - function (originalMethod, window) { - /* eslint-disable no-invalid-this */ - const isOverviewWindow = originalMethod.call(this, window); - return isOverviewWindow && appSpread.windows.includes(window); - /* eslint-enable no-invalid-this */ - }, - ], - [ - // Filter thumbnails to only show current app windows - WorkspaceThumbnail.WorkspaceThumbnail.prototype, '_isOverviewWindow', - function (originalMethod, windowActor) { - /* eslint-disable no-invalid-this */ - const isOverviewWindow = originalMethod.call(this, windowActor); - return isOverviewWindow && appSpread.windows.includes(windowActor.metaWindow); - /* eslint-enable no-invalid-this */ - }, - ]); - - const activitiesButton = Main.panel.statusArea?.activities; - - if (activitiesButton) { - this._signalHandlers.add(Main.overview, 'showing', () => { - activitiesButton.remove_style_pseudo_class('overview'); - activitiesButton.remove_accessible_state(Atk.StateType.CHECKED); - }); - - this._vfuncInjections.add([ - activitiesButton.constructor.prototype, - 'event', - function (event) { - if (event.type() === Clutter.EventType.TOUCH_END || - event.type() === Clutter.EventType.BUTTON_RELEASE) { - if (Main.overview.shouldToggleByCornerOrButton()) - appSpread._restoreDefaultOverview(); - } - return Clutter.EVENT_PROPAGATE; - }, - ], - [ - activitiesButton.constructor.prototype, - 'key_release_event', - function (keyEvent) { - const {keyval} = keyEvent; - if (keyval === Clutter.KEY_Return || keyval === Clutter.KEY_space) { - if (Main.overview.shouldToggleByCornerOrButton()) - appSpread._restoreDefaultOverview(); - } - return Clutter.EVENT_PROPAGATE; - }, - ]); - } - - this._signalHandlers.add(Main.overview.dash.showAppsButton, 'notify::checked', () => { - if (Main.overview.dash.showAppsButton.checked) - this._restoreDefaultOverview(); - }); - - // If closing windows in AppSpread, and only one window left: - // exit app spread and focus remaining window (handled in _hideAppSpread) - this._signalHandlers.add(this.app, 'windows-changed', () => { - this._updateWindows(); - - if (this.windows.length <= 1) - Main.overview.hide(); - }); - - this._disableSearch(); - - Main.overview.show(); - } - - _hideAppSpread() { - if (!this.isInAppSpread) - return; - - if (Main.overview.visible) { - Main.panel.statusArea?.activities.add_style_pseudo_class('overview'); - Main.panel.statusArea?.activities.add_accessible_state(Atk.StateType.CHECKED); - } - - // Restore original behaviour - this.app = null; - this._enableSearch(); - this._methodInjections.clear(); - this._signalHandlers.clear(); - this._vfuncInjections.clear(); - - // Check reason for leaving AppSpread was closing app windows and only one window left... - if (this.windows.length === 1) - Main.activateWindow(this.windows[0]); - - this.windows = []; - } - - _disableSearch() { - if (!SearchController.SearchController.prototype._shouldTriggerSearch) - return; - - if (Main.overview.searchEntry) - Main.overview.searchEntry.opacity = 0; - - this._methodInjections.add( - SearchController.SearchController.prototype, - '_shouldTriggerSearch', () => false); - } - - _enableSearch() { - if (Main.overview.searchEntry) - Main.overview.searchEntry.opacity = 255; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dash.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dash.js deleted file mode 100755 index cdc5b326..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dash.js +++ /dev/null @@ -1,1198 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Clutter, - Gio, - GLib, - GObject, - Shell, - St, -} from './dependencies/gi.js'; - -import { - AppFavorites, - Dash, - DND, - Main, -} from './dependencies/shell/ui.js'; - -import { - Util, -} from './dependencies/shell/misc.js'; - -import { - AppIcons, - Docking, - Theming, - Utils, -} from './imports.js'; - -// module "Dash" does not export DASH_ANIMATION_TIME -// so we just define it like it is defined in Dash; -// taken from https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dash.js -const DASH_ANIMATION_TIME = 200; -const DASH_VISIBILITY_TIMEOUT = 3; - -const Labels = Object.freeze({ - SHOW_MOUNTS: Symbol('show-mounts'), - FIRST_LAST_CHILD_WORKAROUND: Symbol('first-last-child-workaround'), -}); - -/** - * Extend DashItemContainer - * - * - set label position based on dash orientation - * - */ -const DockDashItemContainer = GObject.registerClass( -class DockDashItemContainer extends Dash.DashItemContainer { - _init(position) { - super._init(); - - this.label?.add_style_class_name(Theming.PositionStyleClass[position]); - if (Docking.DockManager.settings.customThemeShrink) - this.label?.add_style_class_name('shrink'); - } - - showLabel() { - return AppIcons.itemShowLabel.call(this); - } - - // we override the method show taken from: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dash.js - // in order to apply a little modification at the end of the animation - // which makes sure that the icon background is not blurry - show(animate) { - if (this.child == null) - return; - - this.ease({ - scale_x: 1, - scale_y: 1, - opacity: 255, - duration: animate ? DASH_ANIMATION_TIME : 0, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - // when the animation is ended, we simulate - // a hover to gain back focus and unblur the - // background - this.set_hover(true); - }, - }); - } -}); - -const DockDashIconsVerticalLayout = GObject.registerClass( - class DockDashIconsVerticalLayout extends Clutter.BoxLayout { - _init() { - super._init({ - orientation: Clutter.Orientation.VERTICAL, - }); - } - - vfunc_get_preferred_height(container, forWidth) { - const [natHeight] = super.vfunc_get_preferred_height(container, forWidth); - return [natHeight, 0]; - } - }); - - -const baseIconSizes = [16, 22, 24, 32, 48, 64, 96, 128]; - -/** - * This class is a fork of the upstream dash class (ui.dash.js) - * - * Summary of changes: - * - disconnect global signals adding a destroy method; - * - play animations even when not in overview mode - * - set a maximum icon size - * - show running and/or favorite applications - * - hide showApps label when the custom menu is shown. - * - add scrollview - * ensure actor is visible on keyfocus inseid the scrollview - * - add 128px icon size, might be useful for hidpi display - * - sync minimization application target position. - * - keep running apps ordered. - */ -export const DockDash = GObject.registerClass({ - Properties: { - 'requires-visibility': GObject.ParamSpec.boolean( - 'requires-visibility', 'requires-visibility', 'requires-visibility', - GObject.ParamFlags.READWRITE, - false), - }, - Signals: { - 'menu-opened': {}, - 'menu-closed': {}, - 'icon-size-changed': {}, - }, -}, class DockDash extends St.Widget { - _init(monitorIndex) { - // Initialize icon variables and size - super._init({ - name: 'dash', - offscreen_redirect: Clutter.OffscreenRedirect.ALWAYS, - layout_manager: new Clutter.BinLayout(), - }); - - this._maxWidth = -1; - this._maxHeight = -1; - this.iconSize = Docking.DockManager.settings.dashMaxIconSize; - this._availableIconSizes = baseIconSizes; - this._shownInitially = false; - this._initializeIconSize(this.iconSize); - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - - this._separator = null; - - this._monitorIndex = monitorIndex; - this._position = Utils.getPosition(); - this._isHorizontal = (this._position === St.Side.TOP) || - (this._position === St.Side.BOTTOM); - - this._dragPlaceholder = null; - this._dragPlaceholderPos = -1; - this._animatingPlaceholdersCount = 0; - this._showLabelTimeoutId = 0; - this._resetHoverTimeoutId = 0; - this._labelShowing = false; - - this._dashContainer = new St.BoxLayout({ - name: 'dashtodockDashContainer', - x_align: Clutter.ActorAlign.CENTER, - y_align: Clutter.ActorAlign.CENTER, - vertical: !this._isHorizontal, - y_expand: this._isHorizontal, - x_expand: !this._isHorizontal, - }); - - this._scrollView = new St.ScrollView({ - name: 'dashtodockDashScrollview', - hscrollbar_policy: this._isHorizontal ? St.PolicyType.EXTERNAL : St.PolicyType.NEVER, - vscrollbar_policy: this._isHorizontal ? St.PolicyType.NEVER : St.PolicyType.EXTERNAL, - x_expand: this._isHorizontal, - y_expand: !this._isHorizontal, - enable_mouse_scrolling: false, - }); - - this._scrollView.connect('scroll-event', this._onScrollEvent.bind(this)); - - this._boxContainer = new St.BoxLayout({ - name: 'dashtodockBoxContainer', - x_align: Clutter.ActorAlign.FILL, - y_align: Clutter.ActorAlign.FILL, - vertical: !this._isHorizontal, - }); - this._boxContainer.add_style_class_name(Theming.PositionStyleClass[this._position]); - - const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL; - this._box = new St.BoxLayout({ - vertical: !this._isHorizontal, - clip_to_allocation: false, - ...!this._isHorizontal ? {layout_manager: new DockDashIconsVerticalLayout()} : {}, - x_align: rtl ? Clutter.ActorAlign.END : Clutter.ActorAlign.START, - y_align: this._isHorizontal ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.START, - y_expand: !this._isHorizontal, - x_expand: this._isHorizontal, - }); - this._box._delegate = this; - this._boxContainer.add_child(this._box); - Utils.addActor(this._scrollView, this._boxContainer); - this._dashContainer.add_child(this._scrollView); - - this._showAppsIcon = new AppIcons.DockShowAppsIcon(this._position); - this._showAppsIcon.show(false); - this._showAppsIcon.icon.setIconSize(this.iconSize); - this._showAppsIcon.x_expand = false; - this._showAppsIcon.y_expand = false; - this.showAppsButton.connect('notify::hover', a => { - if (this._showAppsIcon.get_parent() === this._boxContainer) - this._ensureItemVisibility(a); - }); - if (!this._isHorizontal) - this._showAppsIcon.y_align = Clutter.ActorAlign.START; - this._hookUpLabel(this._showAppsIcon); - this._showAppsIcon.connect('menu-state-changed', (_icon, opened) => { - this._itemMenuStateChanged(this._showAppsIcon, opened); - }); - this.updateShowAppsButton(); - - this._background = new St.Widget({ - style_class: 'dash-background', - y_expand: this._isHorizontal, - x_expand: !this._isHorizontal, - }); - - const sizerBox = new Clutter.Actor(); - sizerBox.add_constraint(new Clutter.BindConstraint({ - source: this._isHorizontal ? this._showAppsIcon.icon : this._dashContainer, - coordinate: Clutter.BindCoordinate.HEIGHT, - })); - sizerBox.add_constraint(new Clutter.BindConstraint({ - source: this._isHorizontal ? this._dashContainer : this._showAppsIcon.icon, - coordinate: Clutter.BindCoordinate.WIDTH, - })); - this._background.add_child(sizerBox); - - this.add_child(this._background); - this.add_child(this._dashContainer); - - this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); - - this._shellSettings = new Gio.Settings({ - schema_id: 'org.gnome.shell', - }); - - this._appSystem = Shell.AppSystem.get_default(); - - this.iconAnimator = new Docking.IconAnimator(this); - - this._signalsHandler.add([ - this._appSystem, - 'installed-changed', - () => { - AppFavorites.getAppFavorites().reload(); - this._queueRedisplay(); - }, - ], [ - AppFavorites.getAppFavorites(), - 'changed', - this._queueRedisplay.bind(this), - ], [ - this._appSystem, - 'app-state-changed', - this._queueRedisplay.bind(this), - ], [ - Main.overview, - 'item-drag-begin', - this._onItemDragBegin.bind(this), - ], [ - Main.overview, - 'item-drag-end', - this._onItemDragEnd.bind(this), - ], [ - Main.overview, - 'item-drag-cancelled', - this._onItemDragCancelled.bind(this), - ], [ - Main.overview, - 'window-drag-begin', - this._onWindowDragBegin.bind(this), - ], [ - Main.overview, - 'window-drag-cancelled', - this._onWindowDragEnd.bind(this), - ], [ - Main.overview, - 'window-drag-end', - this._onWindowDragEnd.bind(this), - ]); - - this.connect('destroy', this._onDestroy.bind(this)); - } - - vfunc_get_preferred_height(forWidth) { - const [minHeight, natHeight] = super.vfunc_get_preferred_height.call(this, forWidth); - if (!this._isHorizontal && this._maxHeight !== -1 && natHeight > this._maxHeight) - return [minHeight, this._maxHeight]; - else - return [minHeight, natHeight]; - } - - vfunc_get_preferred_width(forHeight) { - const [minWidth, natWidth] = super.vfunc_get_preferred_width.call(this, forHeight); - if (this._isHorizontal && this._maxWidth !== -1 && natWidth > this._maxWidth) - return [minWidth, this._maxWidth]; - else - return [minWidth, natWidth]; - } - - get _container() { - return this._dashContainer; - } - - _onDestroy() { - this.iconAnimator.destroy(); - - if (this._requiresVisibilityTimeout) { - GLib.source_remove(this._requiresVisibilityTimeout); - delete this._requiresVisibilityTimeout; - } - - if (this._ensureActorVisibilityTimeoutId) { - GLib.source_remove(this._ensureActorVisibilityTimeoutId); - delete this._ensureActorVisibilityTimeoutId; - } - } - - - _onItemDragBegin(...args) { - return Dash.Dash.prototype._onItemDragBegin.call(this, ...args); - } - - _onItemDragCancelled(...args) { - return Dash.Dash.prototype._onItemDragCancelled.call(this, ...args); - } - - _onItemDragEnd(...args) { - return Dash.Dash.prototype._onItemDragEnd.call(this, ...args); - } - - _endItemDrag(...args) { - return Dash.Dash.prototype._endItemDrag.call(this, ...args); - } - - _onItemDragMotion(...args) { - return Dash.Dash.prototype._onItemDragMotion.call(this, ...args); - } - - _appIdListToHash(...args) { - return Dash.Dash.prototype._appIdListToHash.call(this, ...args); - } - - _queueRedisplay(...args) { - return Dash.Dash.prototype._queueRedisplay.call(this, ...args); - } - - _hookUpLabel(...args) { - return Dash.Dash.prototype._hookUpLabel.call(this, ...args); - } - - _syncLabel(...args) { - return Dash.Dash.prototype._syncLabel.call(this, ...args); - } - - _clearDragPlaceholder(...args) { - return Dash.Dash.prototype._clearDragPlaceholder.call(this, ...args); - } - - _clearEmptyDropTarget(...args) { - return Dash.Dash.prototype._clearEmptyDropTarget.call(this, ...args); - } - - handleDragOver(source, actor, x, y, time) { - let ret; - if (this._isHorizontal) { - ret = Dash.Dash.prototype.handleDragOver.call(this, source, actor, x, y, time); - - if (ret === DND.DragMotionResult.CONTINUE) - return ret; - } else { - const propertyInjections = new Utils.PropertyInjectionsHandler(); - propertyInjections.add(this._box, 'width', { - get: () => this._box.get_children().reduce((a, c) => a + c.height, 0), - }); - - if (this._dragPlaceholder) { - propertyInjections.add(this._dragPlaceholder, 'width', { - get: () => this._dragPlaceholder.height, - }); - } - - ret = Dash.Dash.prototype.handleDragOver.call(this, source, actor, y, x, time); - propertyInjections.destroy(); - - if (ret === DND.DragMotionResult.CONTINUE) - return ret; - - if (this._dragPlaceholder) { - this._dragPlaceholder.child.set_width(this.iconSize / 2); - this._dragPlaceholder.child.set_height(this.iconSize); - - let pos = this._dragPlaceholderPos; - if (this._isHorizontal && - Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) - pos = this._box.get_children() - 1 - pos; - - if (pos !== this._dragPlaceholderPos) { - this._dragPlaceholderPos = pos; - this._box.set_child_at_index(this._dragPlaceholder, - this._dragPlaceholderPos); - } - } - } - - if (this._dragPlaceholder) { - // Ensure the next and previous icon are visible when moving the - // placeholder (we're assuming there's room for both of them) - const children = this._box.get_children(); - if (this._dragPlaceholderPos > 0) { - ensureActorVisibleInScrollView(this._scrollView, - children[this._dragPlaceholderPos - 1]); - } - - if (this._dragPlaceholderPos >= -1 && - this._dragPlaceholderPos < children.length - 1) { - ensureActorVisibleInScrollView(this._scrollView, - children[this._dragPlaceholderPos + 1]); - } - } - - return ret; - } - - acceptDrop(...args) { - return Dash.Dash.prototype.acceptDrop.call(this, ...args); - } - - _onWindowDragBegin(...args) { - return Dash.Dash.prototype._onWindowDragBegin.call(this, ...args); - } - - _onWindowDragEnd(...args) { - return Dash.Dash.prototype._onWindowDragEnd.call(this, ...args); - } - - _onScrollEvent(actor, event) { - // If scroll is not used because the icon is resized, let the scroll event propagate. - if (!Docking.DockManager.settings.iconSizeFixed) - return Clutter.EVENT_PROPAGATE; - - // reset timeout to avid conflicts with the mousehover event - this._ensureItemVisibility(null); - - // Skip to avoid double events mouse - // TODO: Horizontal events are emulated, potentially due to a conflict - // with the workspace switching gesture. - if (!this._isHorizontal && event.is_pointer_emulated()) - return Clutter.EVENT_STOP; - - - let adjustment, delta = 0; - - if (this._isHorizontal) - adjustment = this._scrollView.get_hscroll_bar().get_adjustment(); - else - adjustment = this._scrollView.get_vscroll_bar().get_adjustment(); - - const increment = adjustment.step_increment; - - if (this._isHorizontal) { - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.LEFT: - delta = -increment; - break; - case Clutter.ScrollDirection.RIGHT: - delta = Number(increment); - break; - case Clutter.ScrollDirection.SMOOTH: { - const [dx] = event.get_scroll_delta(); - delta = dx * increment; - break; - } - } - } else { - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.UP: - delta = -increment; - break; - case Clutter.ScrollDirection.DOWN: - delta = Number(increment); - break; - case Clutter.ScrollDirection.SMOOTH: { - const [, dy] = event.get_scroll_delta(); - delta = dy * increment; - break; - } - } - } - - const value = adjustment.get_value(); - - // TODO: Remove this if possible. - if (Number.isNaN(value)) - adjustment.set_value(delta); - else - adjustment.set_value(value + delta); - - return Clutter.EVENT_STOP; - } - - _ensureItemVisibility(actor) { - if (actor?.hover) { - const destroyId = - actor.connect('destroy', () => this._ensureItemVisibility(null)); - this._ensureActorVisibilityTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, 100, () => { - actor.disconnect(destroyId); - ensureActorVisibleInScrollView(this._scrollView, actor); - this._ensureActorVisibilityTimeoutId = 0; - return GLib.SOURCE_REMOVE; - }); - } else if (this._ensureActorVisibilityTimeoutId) { - GLib.source_remove(this._ensureActorVisibilityTimeoutId); - this._ensureActorVisibilityTimeoutId = 0; - } - } - - _createAppItem(app) { - const appIcon = new AppIcons.makeAppIcon(app, this._monitorIndex, this.iconAnimator); - - if (appIcon._draggable) { - appIcon._draggable.connect('drag-begin', () => { - appIcon.opacity = 50; - }); - appIcon._draggable.connect('drag-end', () => { - appIcon.opacity = 255; - }); - } - - appIcon.connect('menu-state-changed', (_, opened) => { - this._itemMenuStateChanged(item, opened); - }); - - const item = new DockDashItemContainer(this._position); - item.setChild(appIcon); - - appIcon.connect('notify::hover', a => this._ensureItemVisibility(a)); - appIcon.connect('clicked', actor => { - ensureActorVisibleInScrollView(this._scrollView, actor); - }); - - appIcon.connect('key-focus-in', actor => { - const [xShift, yShift] = ensureActorVisibleInScrollView(this._scrollView, actor); - - // This signal is triggered also by mouse click. The popup menu is opened at the original - // coordinates. Thus correct for the shift which is going to be applied to the scrollview. - if (appIcon._menu) { - appIcon._menu._boxPointer.xOffset = -xShift; - appIcon._menu._boxPointer.yOffset = -yShift; - } - }); - - appIcon.connect('notify::focused', () => { - const {settings} = Docking.DockManager; - if (appIcon.focused && settings.scrollToFocusedApplication) - ensureActorVisibleInScrollView(this._scrollView, item); - }); - - appIcon.connect('notify::urgent', () => { - if (appIcon.urgent) { - ensureActorVisibleInScrollView(this._scrollView, item); - if (Docking.DockManager.settings.showDockUrgentNotify) - this._requireVisibility(); - } - }); - - // Override default AppIcon label_actor, now the - // accessible_name is set at DashItemContainer.setLabelText - appIcon.label_actor = null; - item.setLabelText(app.get_name()); - - appIcon.icon.setIconSize(this.iconSize); - this._hookUpLabel(item, appIcon); - - item.connect('notify::position', () => appIcon.updateIconGeometry()); - item.connect('notify::size', () => appIcon.updateIconGeometry()); - - return item; - } - - _requireVisibility() { - this.requiresVisibility = true; - - if (this._requiresVisibilityTimeout) - GLib.source_remove(this._requiresVisibilityTimeout); - - this._requiresVisibilityTimeout = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, - DASH_VISIBILITY_TIMEOUT, () => { - this._requiresVisibilityTimeout = 0; - this.requiresVisibility = false; - }); - } - - /** - * Return an array with the "proper" appIcons currently in the dash - */ - getAppIcons() { - // Only consider children which are "proper" - // icons (i.e. ignoring drag placeholders) and which are not - // animating out (which means they will be destroyed at the end of - // the animation) - const iconChildren = this._box.get_children().filter(actor => { - return actor.child && - !!actor.child.icon && - !actor.animatingOut; - }); - - const appIcons = iconChildren.map(actor => { - return actor.child; - }); - - return appIcons; - } - - _itemMenuStateChanged(item, opened) { - Dash.Dash.prototype._itemMenuStateChanged.call(this, item, opened); - - if (opened) { - this.emit('menu-opened'); - } else { - // I want to listen from outside when a menu is closed. I used to - // add a custom signal to the appIcon, since gnome 3.8 the signal - // calling this callback was added upstream. - this.emit('menu-closed'); - } - } - - _adjustIconSize() { - // For the icon size, we only consider children which are "proper" - // icons (i.e. ignoring drag placeholders) and which are not - // animating out (which means they will be destroyed at the end of - // the animation) - const iconChildren = this._box.get_children().filter(actor => { - return actor.child && - actor.child._delegate && - actor.child._delegate.icon && - !actor.animatingOut; - }); - - iconChildren.push(this._showAppsIcon); - - if (this._maxWidth === -1 && this._maxHeight === -1) - return; - - // Check if the container is present in the stage. This avoids critical - // errors when unlocking the screen - if (!this._container.get_stage()) - return; - - const themeNode = this._dashContainer.get_theme_node(); - const maxAllocation = new Clutter.ActorBox({ - x1: 0, - y1: 0, - x2: this._isHorizontal ? this._maxWidth : 42 /* whatever */, - y2: this._isHorizontal ? 42 : this._maxHeight, - }); - const maxContent = themeNode.get_content_box(maxAllocation); - let availSpace; - if (this._isHorizontal) - availSpace = maxContent.get_width(); - else - availSpace = maxContent.get_height(); - - const spacing = themeNode.get_length('spacing'); - - const [{child: firstButton}] = iconChildren; - const {child: firstIcon} = firstButton?.icon ?? {child: null}; - - // if no icons there's nothing to adjust - if (!firstIcon) - return; - - // Enforce valid spacings during the size request - firstIcon.ensure_style(); - const [, , iconWidth, iconHeight] = firstIcon.get_preferred_size(); - const [, , buttonWidth, buttonHeight] = firstButton.get_preferred_size(); - - if (this._isHorizontal) { - // Subtract icon padding and box spacing from the available width - availSpace -= iconChildren.length * (buttonWidth - iconWidth) + - (iconChildren.length - 1) * spacing; - - if (this._separator) { - const [, , separatorWidth] = this._separator.get_preferred_size(); - availSpace -= separatorWidth + spacing; - } - } else { - // Subtract icon padding and box spacing from the available height - availSpace -= iconChildren.length * (buttonHeight - iconHeight) + - (iconChildren.length - 1) * spacing; - - if (this._separator) { - const [, , , separatorHeight] = this._separator.get_preferred_size(); - availSpace -= separatorHeight + spacing; - } - } - - const maxIconSize = availSpace / iconChildren.length; - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const iconSizes = this._availableIconSizes.map(s => s * scaleFactor); - - let [newIconSize] = this._availableIconSizes; - for (let i = 0; i < iconSizes.length; i++) { - if (iconSizes[i] <= maxIconSize) - newIconSize = this._availableIconSizes[i]; - } - - if (newIconSize === this.iconSize) - return; - - const oldIconSize = this.iconSize; - this.iconSize = newIconSize; - this.emit('icon-size-changed'); - - const scale = oldIconSize / newIconSize; - for (let i = 0; i < iconChildren.length; i++) { - const {icon} = iconChildren[i].child._delegate; - - // Set the new size immediately, to keep the icons' sizes - // in sync with this.iconSize - icon.setIconSize(this.iconSize); - - // Don't animate the icon size change when the overview - // is transitioning, not visible or when initially filling - // the dash - if (!Main.overview.visible || Main.overview.animationInProgress || - !this._shownInitially) - continue; - - const [targetWidth, targetHeight] = icon.icon.get_size(); - - // Scale the icon's texture to the previous size and - // tween to the new size - icon.icon.set_size(icon.icon.width * scale, - icon.icon.height * scale); - - icon.icon.ease({ - width: targetWidth, - height: targetHeight, - duration: DASH_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - - if (this._separator) { - const animateProperties = this._isHorizontal - ? {height: this.iconSize} : {width: this.iconSize}; - - this._separator.ease({ - ...animateProperties, - duration: DASH_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - } - - _redisplay() { - const favorites = AppFavorites.getAppFavorites().getFavoriteMap(); - - let running = this._appSystem.get_running(); - const dockManager = Docking.DockManager.getDefault(); - const {settings} = dockManager; - - this._scrollView.set({ - xAlign: Clutter.ActorAlign.FILL, - yAlign: Clutter.ActorAlign.FILL, - }); - if (dockManager.settings.dockExtended) { - if (!this._isHorizontal) { - this._scrollView.yAlign = dockManager.settings.alwaysCenterIcons - ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.START; - } else { - this._scrollView.xAlign = dockManager.settings.alwaysCenterIcons - ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.START; - } - } - - if (settings.isolateWorkspaces || - settings.isolateMonitors) { - // When using isolation, we filter out apps that have no windows in - // the current workspace - const monitorIndex = this._monitorIndex; - running = running.filter(app => - AppIcons.getInterestingWindows(app.get_windows(), monitorIndex).length); - } - - const children = this._box.get_children().filter(actor => { - return actor.child && - actor.child._delegate && - actor.child._delegate.app; - }); - // Apps currently in the dash - let oldApps = children.map(actor => actor.child._delegate.app); - // Apps supposed to be in the dash - const newApps = []; - - const {showFavorites} = settings; - if (showFavorites) - newApps.push(...Object.values(favorites)); - - if (settings.showRunning) { - // We reorder the running apps so that they don't change position on the - // dash with every redisplay() call - - // First: add the apps from the oldApps list that are still running - oldApps.forEach(oldApp => { - const index = running.indexOf(oldApp); - if (index > -1) { - const [app] = running.splice(index, 1); - if (!showFavorites || !(app.get_id() in favorites)) - newApps.push(app); - } - }); - - // Second: add the new apps - running.forEach(app => { - if (!showFavorites || !(app.get_id() in favorites)) - newApps.push(app); - }); - } - - this._signalsHandler.removeWithLabel(Labels.SHOW_MOUNTS); - if (dockManager.removables) { - this._signalsHandler.addWithLabel(Labels.SHOW_MOUNTS, - dockManager.removables, 'changed', this._queueRedisplay.bind(this)); - dockManager.removables.getApps().forEach(removable => { - if (!newApps.includes(removable)) - newApps.push(removable); - }); - } else { - oldApps = oldApps.filter(app => !app.location || app.isTrash); - } - - if (dockManager.trash) { - const trashApp = dockManager.trash.getApp(); - if (!newApps.includes(trashApp)) - newApps.push(trashApp); - } else { - oldApps = oldApps.filter(app => !app.isTrash); - } - - // Temporary remove the separator so that we don't compute to position icons - const oldSeparatorPos = this._box.get_children().indexOf(this._separator); - if (this._separator) - this._box.remove_child(this._separator); - - // Figure out the actual changes to the list of items; we iterate - // over both the list of items currently in the dash and the list - // of items expected there, and collect additions and removals. - // Moves are both an addition and a removal, where the order of - // the operations depends on whether we encounter the position - // where the item has been added first or the one from where it - // was removed. - // There is an assumption that only one item is moved at a given - // time; when moving several items at once, everything will still - // end up at the right position, but there might be additional - // additions/removals (e.g. it might remove all the launchers - // and add them back in the new order even if a smaller set of - // additions and removals is possible). - // If above assumptions turns out to be a problem, we might need - // to use a more sophisticated algorithm, e.g. Longest Common - // Subsequence as used by diff. - - const addedItems = []; - const removedActors = []; - - let newIndex = 0; - let oldIndex = 0; - while (newIndex < newApps.length || oldIndex < oldApps.length) { - const oldApp = oldApps.length > oldIndex ? oldApps[oldIndex] : null; - const newApp = newApps.length > newIndex ? newApps[newIndex] : null; - - // No change at oldIndex/newIndex - if (oldApp === newApp) { - oldIndex++; - newIndex++; - continue; - } - - // App removed at oldIndex - if (oldApp && !newApps.includes(oldApp)) { - removedActors.push(children[oldIndex]); - oldIndex++; - continue; - } - - // App added at newIndex - if (newApp && !oldApps.includes(newApp)) { - addedItems.push({ - app: newApp, - item: this._createAppItem(newApp), - pos: newIndex, - }); - newIndex++; - continue; - } - - // App moved - const nextApp = newApps.length > newIndex + 1 - ? newApps[newIndex + 1] : null; - const insertHere = nextApp && nextApp === oldApp; - const alreadyRemoved = removedActors.reduce((result, actor) => { - const removedApp = actor.child._delegate.app; - return result || removedApp === newApp; - }, false); - - if (insertHere || alreadyRemoved) { - const newItem = this._createAppItem(newApp); - addedItems.push({ - app: newApp, - item: newItem, - pos: newIndex + removedActors.length, - }); - newIndex++; - } else { - removedActors.push(children[oldIndex]); - oldIndex++; - } - } - - for (let i = 0; i < addedItems.length; i++) { - this._box.insert_child_at_index(addedItems[i].item, - addedItems[i].pos); - } - - for (let i = 0; i < removedActors.length; i++) { - const item = removedActors[i]; - - // Don't animate item removal when the overview is transitioning - // or hidden - if (!Main.overview.animationInProgress) - item.animateOutAndDestroy(); - else - item.destroy(); - } - - // Update separator - const nFavorites = Object.keys(favorites).length; - const nIcons = children.length + addedItems.length - removedActors.length; - if (nFavorites > 0 && nFavorites < nIcons) { - if (!this._separator) { - this._separator = new St.Widget({ - style_class: 'dash-separator', - x_align: this._isHorizontal - ? Clutter.ActorAlign.FILL : Clutter.ActorAlign.CENTER, - y_align: this._isHorizontal - ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.FILL, - width: this._isHorizontal ? -1 : this.iconSize, - height: this._isHorizontal ? this.iconSize : -1, - reactive: true, - track_hover: true, - }); - this._separator.connect('notify::hover', a => this._ensureItemVisibility(a)); - } - let pos = nFavorites + this._animatingPlaceholdersCount; - if (this._dragPlaceholder) - pos++; - const removedFavorites = removedActors.filter(a => - children.indexOf(a) < oldSeparatorPos); - pos += removedFavorites.length; - this._box.insert_child_at_index(this._separator, pos); - } else if (this._separator) { - this._separator.destroy(); - this._separator = null; - } - - this._adjustIconSize(); - - // Skip animations on first run when adding the initial set - // of items, to avoid all items zooming in at once - const animate = this._shownInitially && - !Main.layoutManager._startingUp; - - if (!this._shownInitially) - this._shownInitially = true; - - addedItems.forEach(({item}) => item.show(animate)); - - // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 - // Without it, StBoxLayout may use a stale size cache - this._box.queue_relayout(); - - // This will update the size, and the corresponding number for each icon - this._updateNumberOverlay(); - - this.updateShowAppsButton(); - } - - _updateNumberOverlay() { - const appIcons = this.getAppIcons(); - let counter = 1; - appIcons.forEach(icon => { - if (counter < 10) { - icon.setNumberOverlay(counter); - counter++; - } else if (counter === 10) { - icon.setNumberOverlay(0); - counter++; - } else { - // No overlay after 10 - icon.setNumberOverlay(-1); - } - icon.updateNumberOverlay(); - }); - } - - toggleNumberOverlay(activate) { - const appIcons = this.getAppIcons(); - appIcons.forEach(icon => { - icon.toggleNumberOverlay(activate); - }); - } - - _initializeIconSize(maxSize) { - const maxAllowed = baseIconSizes[baseIconSizes.length - 1]; - maxSize = Math.min(maxSize, maxAllowed); - - if (Docking.DockManager.settings.iconSizeFixed) { - this._availableIconSizes = [maxSize]; - } else { - this._availableIconSizes = baseIconSizes.filter(val => { - return val < maxSize; - }); - this._availableIconSizes.push(maxSize); - } - } - - setIconSize(maxSize, doNotAnimate) { - this._initializeIconSize(maxSize); - - if (doNotAnimate) - this._shownInitially = false; - - this._queueRedisplay(); - } - - /** - * Reset the displayed apps icon to maintain the correct order when changing - * show favorites/show running settings - */ - resetAppIcons() { - const children = this._box.get_children().filter(actor => { - return actor.child && - !!actor.child.icon; - }); - for (let i = 0; i < children.length; i++) { - const item = children[i]; - item.destroy(); - } - - // to avoid ugly animations, just suppress them like when dash is first loaded. - this._shownInitially = false; - this._redisplay(); - } - - get showAppsButton() { - return this._showAppsIcon.toggleButton; - } - - showShowAppsButton() { - this._showAppsIcon.visible = true; - this._showAppsIcon.show(true); - this.updateShowAppsButton(); - } - - hideShowAppsButton() { - this._showAppsIcon.visible = false; - } - - setMaxSize(maxWidth, maxHeight) { - if (this._maxWidth === maxWidth && - this._maxHeight === maxHeight) - return; - - this._maxWidth = maxWidth; - this._maxHeight = maxHeight; - this._queueRedisplay(); - } - - updateShowAppsButton() { - if (this._showAppsIcon.get_parent() && !this._showAppsIcon.visible) - return; - - const {settings} = Docking.DockManager; - const notifiedProperties = []; - const showAppsContainer = settings.showAppsAlwaysInTheEdge || !settings.dockExtended - ? this._dashContainer : this._boxContainer; - - this._signalsHandler.addWithLabel(Labels.FIRST_LAST_CHILD_WORKAROUND, - showAppsContainer, 'notify', - (_obj, pspec) => notifiedProperties.push(pspec.name)); - - if (this._showAppsIcon.get_parent() !== showAppsContainer) { - this._showAppsIcon.get_parent()?.remove_child(this._showAppsIcon); - - if (Docking.DockManager.settings.showAppsAtTop) - showAppsContainer.insert_child_below(this._showAppsIcon, null); - else - showAppsContainer.insert_child_above(this._showAppsIcon, null); - } else if (settings.showAppsAtTop) { - showAppsContainer.set_child_below_sibling(this._showAppsIcon, null); - } else { - showAppsContainer.set_child_above_sibling(this._showAppsIcon, null); - } - - this._signalsHandler.removeWithLabel(Labels.FIRST_LAST_CHILD_WORKAROUND); - - // This is indeed ugly, but we need to ensure that the last and first - // visible widgets are re-computed by St, that is buggy because of a - // mutter issue that is being fixed: - // https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2047 - if (!notifiedProperties.includes('first-child')) - showAppsContainer.notify('first-child'); - if (!notifiedProperties.includes('last-child')) - showAppsContainer.notify('last-child'); - } -}); - - -/** - * This is a copy of the same function in utils.js, but also adjust horizontal scrolling - * and perform few further checks on the current value to avoid changing the values when - * it would be clamp to the current one in any case. - * Return the amount of shift applied - * - * @param scrollView - * @param actor - */ -function ensureActorVisibleInScrollView(scrollView, actor) { - // access to scrollView.[hv]scroll was deprecated in gnome 46 - // instead, adjustment can be accessed directly - // keep old way for backwards compatibility (gnome <= 45) - const vAdjustment = scrollView.vadjustment ?? scrollView.vscroll.adjustment; - const hAdjustment = scrollView.hadjustment ?? scrollView.hscroll.adjustment; - const {value: vValue0, pageSize: vPageSize, upper: vUpper} = vAdjustment; - const {value: hValue0, pageSize: hPageSize, upper: hUpper} = hAdjustment; - let [hValue, vValue] = [hValue0, vValue0]; - let vOffset = 0; - let hOffset = 0; - - const fade = scrollView.get_effect('fade'); - if (fade) { - vOffset = fade.fade_margins.top; - hOffset = fade.fade_margins.left; - } - - const box = actor.get_allocation_box(); - let {y1} = box, {y2} = box, {x1} = box, {x2} = box; - - let parent = actor.get_parent(); - while (parent !== scrollView) { - if (!parent) - throw new Error('Actor not in scroll view'); - - const parentBox = parent.get_allocation_box(); - y1 += parentBox.y1; - y2 += parentBox.y1; - x1 += parentBox.x1; - x2 += parentBox.x1; - parent = parent.get_parent(); - } - - if (y1 < vValue + vOffset) - vValue = Math.max(0, y1 - vOffset); - else if (vValue < vUpper - vPageSize && y2 > vValue + vPageSize - vOffset) - vValue = Math.min(vUpper - vPageSize, y2 + vOffset - vPageSize); - - if (x1 < hValue + hOffset) - hValue = Math.max(0, x1 - hOffset); - else if (hValue < hUpper - hPageSize && x2 > hValue + hPageSize - hOffset) - hValue = Math.min(hUpper - hPageSize, x2 + hOffset - hPageSize); - - if (vValue !== vValue0) { - vAdjustment.ease(vValue, { - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: Util.SCROLL_TIME, - }); - } - - if (hValue !== hValue0) { - hAdjustment.ease(hValue, { - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - duration: Util.SCROLL_TIME, - }); - } - - return [hValue - hValue0, vValue - vValue0]; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dbusmenuUtils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dbusmenuUtils.js deleted file mode 100755 index d992b1ae..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dbusmenuUtils.js +++ /dev/null @@ -1,280 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Atk, - Clutter, - Gio, - GLib, - St, -} from './dependencies/gi.js'; - -import {PopupMenu} from './dependencies/shell/ui.js'; - -import {Utils} from './imports.js'; - -// Dbusmenu features not (yet) supported: -// -// * The CHILD_DISPLAY property -// -// This seems to have only one possible value in the Dbusmenu API, so -// there's little point in depending on it--the code in libdbusmenu sets it -// if and only if an item has children, so for our purposes it's simpler -// and more intuitive to just check children.length. (This does ignore the -// possibility of a program not using libdbusmenu and setting CHILD_DISPLAY -// independently, perhaps to indicate that an childless menu item should -// nevertheless be displayed like a submenu.) -// -// * Children more than two levels deep -// -// PopupMenu doesn't seem to support submenus in submenus. -// -// * Shortcut keys -// -// If these keys are supposed to be installed as global shortcuts, we'd -// have to query these aggressively and not wait for the DBus menu to be -// mapped to a popup menu. A shortcut key that only works once the popup -// menu is open and has key focus is possibly of marginal value. - -/** - * - */ -export async function haveDBusMenu() { - try { - const {default: DBusMenu} = await import('gi://Dbusmenu'); - return DBusMenu; - } catch (e) { - log(`Failed to import DBusMenu, quicklists are not available: ${e}`); - return null; - } -} - -const DBusMenu = await haveDBusMenu(); - -/** - * @param dbusmenuItem - * @param deep - */ -export function makePopupMenuItem(dbusmenuItem, deep) { - // These are the only properties guaranteed to be available when the root - // item is first announced. Other properties might be loaded already, but - // be sure to connect to Dbusmenu.MENUITEM_SIGNAL_PROPERTY_CHANGED to get - // the most up-to-date values in case they aren't. - const itemType = dbusmenuItem.property_get(DBusMenu.MENUITEM_PROP_TYPE); - const label = dbusmenuItem.property_get(DBusMenu.MENUITEM_PROP_LABEL); - const visible = dbusmenuItem.property_get_bool(DBusMenu.MENUITEM_PROP_VISIBLE); - const enabled = dbusmenuItem.property_get_bool(DBusMenu.MENUITEM_PROP_ENABLED); - const accessibleDesc = dbusmenuItem.property_get(DBusMenu.MENUITEM_PROP_ACCESSIBLE_DESC); - // const childDisplay = dbusmenuItem.property_get(Dbusmenu.MENUITEM_PROP_CHILD_DISPLAY); - - let item; - const signalsHandler = new Utils.GlobalSignalsHandler(); - const wantIcon = itemType === DBusMenu.CLIENT_TYPES_IMAGE; - - // If the basic type of the menu item needs to change, call this. - const recreateItem = () => { - const newItem = makePopupMenuItem(dbusmenuItem, deep); - const parentMenu = item._parent; - parentMenu.addMenuItem(newItem); - // Reminder: Clutter thinks of later entries in the child list as - // "above" earlier ones, so "above" here means "below" in terms of the - // menu's vertical order. - parentMenu.actor.set_child_above_sibling(newItem.actor, item.actor); - if (newItem.menu) - parentMenu.actor.set_child_above_sibling(newItem.menu.actor, newItem.actor); - - parentMenu.actor.remove_child(item.actor); - item.destroy(); - item = null; - }; - - const updateDisposition = () => { - const disposition = dbusmenuItem.property_get(DBusMenu.MENUITEM_PROP_DISPOSITION); - let iconName = null; - switch (disposition) { - case DBusMenu.MENUITEM_DISPOSITION_ALERT: - case DBusMenu.MENUITEM_DISPOSITION_WARNING: - iconName = 'dialog-warning-symbolic'; - break; - case DBusMenu.MENUITEM_DISPOSITION_INFORMATIVE: - iconName = 'dialog-information-symbolic'; - break; - } - if (iconName) { - item._dispositionIcon = new St.Icon({ - icon_name: iconName, - style_class: 'popup-menu-icon', - y_align: Clutter.ActorAlign.CENTER, - y_expand: true, - }); - let expander; - for (let child = item.label.get_next_sibling(); ; child = child.get_next_sibling()) { - if (!child) { - expander = new St.Bin({ - style_class: 'popup-menu-item-expander', - x_expand: true, - }); - item.actor.add_child(expander); - break; - } else if (child instanceof St.Widget && - child.has_style_class_name('popup-menu-item-expander')) { - expander = child; - break; - } - } - item.actor.insert_child_above(item._dispositionIcon, expander); - } else if (item._dispositionIcon) { - item.actor.remove_child(item._dispositionIcon); - item._dispositionIcon = null; - } - }; - - const updateIcon = () => { - if (!wantIcon) - return; - - const iconData = dbusmenuItem.property_get_byte_array(DBusMenu.MENUITEM_PROP_ICON_DATA); - const iconName = dbusmenuItem.property_get(DBusMenu.MENUITEM_PROP_ICON_NAME); - if (iconName) - item.icon.icon_name = iconName; - else if (iconData.length) - item.icon.gicon = Gio.BytesIcon.new(iconData); - }; - - const updateOrnament = () => { - const toggleType = dbusmenuItem.property_get(DBusMenu.MENUITEM_PROP_TOGGLE_TYPE); - switch (toggleType) { - case DBusMenu.MENUITEM_TOGGLE_CHECK: - item.actor.accessible_role = Atk.Role.CHECK_MENU_ITEM; - break; - case DBusMenu.MENUITEM_TOGGLE_RADIO: - item.actor.accessible_role = Atk.Role.RADIO_MENU_ITEM; - break; - default: - item.actor.accessible_role = Atk.Role.MENU_ITEM; - } - let ornament = PopupMenu.Ornament.NONE; - const state = dbusmenuItem.property_get_int(DBusMenu.MENUITEM_PROP_TOGGLE_STATE); - if (state === DBusMenu.MENUITEM_TOGGLE_STATE_UNKNOWN) { - // PopupMenu doesn't natively support an "unknown" ornament, but we - // can hack one in: - item.setOrnament(ornament); - item.actor.add_accessible_state(Atk.StateType.INDETERMINATE); - item._ornamentLabel.text = '\u2501'; - item.actor.remove_style_pseudo_class('checked'); - } else { - item.actor.remove_accessible_state(Atk.StateType.INDETERMINATE); - if (state === DBusMenu.MENUITEM_TOGGLE_STATE_CHECKED) { - if (toggleType === DBusMenu.MENUITEM_TOGGLE_CHECK) - ornament = PopupMenu.Ornament.CHECK; - else if (toggleType === DBusMenu.MENUITEM_TOGGLE_RADIO) - ornament = PopupMenu.Ornament.DOT; - - item.actor.add_style_pseudo_class('checked'); - } else { - item.actor.remove_style_pseudo_class('checked'); - } - item.setOrnament(ornament); - } - }; - - const onPropertyChanged = (_, name, value) => { - // `value` is null when a property is cleared, so handle those cases - // with sensible defaults. - switch (name) { - case DBusMenu.MENUITEM_PROP_TYPE: - recreateItem(); - break; - case DBusMenu.MENUITEM_PROP_ENABLED: - item.setSensitive(value ? value.unpack() : false); - break; - case DBusMenu.MENUITEM_PROP_LABEL: - item.label.text = value ? value.unpack() : ''; - break; - case DBusMenu.MENUITEM_PROP_VISIBLE: - item.actor.visible = value ? value.unpack() : false; - break; - case DBusMenu.MENUITEM_PROP_DISPOSITION: - updateDisposition(); - break; - case DBusMenu.MENUITEM_PROP_ACCESSIBLE_DESC: - item.actor.get_accessible().accessible_description = value && value.unpack() || ''; - break; - case DBusMenu.MENUITEM_PROP_ICON_DATA: - case DBusMenu.MENUITEM_PROP_ICON_NAME: - updateIcon(); - break; - case DBusMenu.MENUITEM_PROP_TOGGLE_TYPE: - case DBusMenu.MENUITEM_PROP_TOGGLE_STATE: - updateOrnament(); - break; - } - }; - - - // Start actually building the menu item. - const children = dbusmenuItem.get_children(); - if (children.length && !deep) { - // Make a submenu. - item = new PopupMenu.PopupSubMenuMenuItem(label, wantIcon); - const updateChildren = () => { - const itemChildren = dbusmenuItem.get_children(); - if (!itemChildren.length) { - recreateItem(); - return; - } - - item.menu.removeAll(); - itemChildren.forEach(remoteChild => - item.menu.addMenuItem(makePopupMenuItem(remoteChild, true))); - }; - updateChildren(); - signalsHandler.add( - [dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_CHILD_ADDED, updateChildren], - [dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_CHILD_MOVED, updateChildren], - [dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_CHILD_REMOVED, updateChildren]); - } else { - // Don't make a submenu. - if (!deep) { - // We only have the potential to get a submenu if we aren't deep. - signalsHandler.add( - [dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_CHILD_ADDED, recreateItem], - [dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_CHILD_MOVED, recreateItem], - [dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_CHILD_REMOVED, recreateItem]); - } - - if (itemType === DBusMenu.CLIENT_TYPES_SEPARATOR) { - item = new PopupMenu.PopupSeparatorMenuItem(); - } else if (wantIcon) { - item = new PopupMenu.PopupImageMenuItem(label, null); - item.icon = item._icon; - } else { - item = new PopupMenu.PopupMenuItem(label); - } - } - - // Set common initial properties. - item.actor.visible = visible; - item.setSensitive(enabled); - if (accessibleDesc) - item.actor.get_accessible().accessible_description = accessibleDesc; - - updateDisposition(); - updateIcon(); - updateOrnament(); - - // Prevent an initial resize flicker. - if (wantIcon) - item.icon.icon_size = 16; - - - signalsHandler.add(dbusmenuItem, DBusMenu.MENUITEM_SIGNAL_PROPERTY_CHANGED, onPropertyChanged); - - // Connections on item will be lost when item is disposed; there's no need - // to add them to signalsHandler. - item.connect('activate', () => - dbusmenuItem.handle_event(DBusMenu.MENUITEM_EVENT_ACTIVATED, - new GLib.Variant('i', 0), Math.floor(Date.now() / 1000))); - item.connect('destroy', () => signalsHandler.destroy()); - - return item; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/gi.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/gi.js deleted file mode 100755 index e715f90e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/gi.js +++ /dev/null @@ -1,12 +0,0 @@ -export {default as Atk} from 'gi://Atk'; -export {default as Clutter} from 'gi://Clutter'; -export {default as GLib} from 'gi://GLib'; -export {default as GObject} from 'gi://GObject'; -export {default as GdkPixbuf} from 'gi://GdkPixbuf'; -export {default as Gio} from 'gi://Gio'; -export {default as Meta} from 'gi://Meta'; -export {default as Mtk} from 'gi://Mtk'; -export {default as Pango} from 'gi://Pango'; -export {default as Shell} from 'gi://Shell'; -export {default as St} from 'gi://St'; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/extensions/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/extensions/extension.js deleted file mode 100755 index bd9db981..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/extensions/extension.js +++ /dev/null @@ -1 +0,0 @@ -export * as Extension from 'resource:///org/gnome/shell/extensions/extension.js'; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/misc.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/misc.js deleted file mode 100755 index cfd4b959..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/misc.js +++ /dev/null @@ -1,5 +0,0 @@ -export * as AnimationUtils from 'resource:///org/gnome/shell/misc/animationUtils.js'; -export * as Config from 'resource:///org/gnome/shell/misc/config.js'; -export * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js'; -export * as ParentalControlsManager from 'resource:///org/gnome/shell/misc/parentalControlsManager.js'; -export * as Util from 'resource:///org/gnome/shell/misc/util.js'; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/ui.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/ui.js deleted file mode 100755 index 40fa4ca3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/dependencies/shell/ui.js +++ /dev/null @@ -1,17 +0,0 @@ -export * as AppDisplay from 'resource:///org/gnome/shell/ui/appDisplay.js'; -export * as AppFavorites from 'resource:///org/gnome/shell/ui/appFavorites.js'; -export * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; -export * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -export * as Dash from 'resource:///org/gnome/shell/ui/dash.js'; -export * as Layout from 'resource:///org/gnome/shell/ui/layout.js'; -export * as Main from 'resource:///org/gnome/shell/ui/main.js'; -export * as Overview from 'resource:///org/gnome/shell/ui/overview.js'; -export * as OverviewControls from 'resource:///org/gnome/shell/ui/overviewControls.js'; -export * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js'; -export * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -export * as SearchController from 'resource:///org/gnome/shell/ui/searchController.js'; -export * as ShellMountOperation from 'resource:///org/gnome/shell/ui/shellMountOperation.js'; -export * as Workspace from 'resource:///org/gnome/shell/ui/workspace.js'; -export * as WorkspaceSwitcherPopup from 'resource:///org/gnome/shell/ui/workspaceSwitcherPopup.js'; -export * as WorkspaceThumbnail from 'resource:///org/gnome/shell/ui/workspaceThumbnail.js'; -export * as WorkspacesView from 'resource:///org/gnome/shell/ui/workspacesView.js'; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/desktopIconsIntegration.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/desktopIconsIntegration.js deleted file mode 100755 index e6375013..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/desktopIconsIntegration.js +++ /dev/null @@ -1,165 +0,0 @@ -/* - * The code in this file is distributed under a "1-clause BSD license", - * which makes it compatible with GPLv2 and GPLv3 too, and others. - * - * License text: - * - * Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com) - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * Integration class - * - * This class must be added to other extensions in order to integrate - * them with Desktop Icons NG. It allows an extension to notify how much margin - * it uses in each side of each monitor. - * - * DON'T SEND PATCHES TO THIS FILE TO THE EXTENSION MAINTAINER. SEND THEM TO - * DESKTOP ICONS NG MAINTAINER: https://gitlab.com/rastersoft/desktop-icons-ng - * - * In the *enable()* function, create a *DesktopIconsUsableAreaClass()* - * object with - * - * new DesktopIconsIntegration.DesktopIconsUsableAreaClass(object); - * - * Now, in the *disable()* function just call to the *destroy()* method before - * nullifying the pointer. You must create a new object in enable() the next - * time the extension is enabled. - * - * In your code, every time you change the margins, you should call first to - * *resetMargins()* method to clear the current margins, and then call to - * *setMargins(...)* method as many times as you need to set the margins in each - * monitor. You don't need to call it for all the monitors, only for those where - * you are painting something. If you don't set values for a monitor, they will - * be considered zero. - * - * The margins values are relative to the monitor border. - * - *******************************************************************************/ - -import GLib from 'gi://GLib'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as ExtensionUtils from 'resource:///org/gnome/shell/misc/extensionUtils.js'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -const IDENTIFIER_UUID = '130cbc66-235c-4bd6-8571-98d2d8bba5e2'; - -export class DesktopIconsUsableAreaClass { - constructor() { - const Me = Extension.lookupByURL(import.meta.url); - this._UUID = Me.uuid; - this._extensionManager = Main.extensionManager; - this._timedMarginsID = 0; - this._margins = {}; - this._emID = this._extensionManager.connect('extension-state-changed', (_obj, extension) => { - if (!extension) - return; - - // If an extension is being enabled and lacks the - // DesktopIconsUsableArea object, we can avoid launching a refresh - if (extension.state === ExtensionUtils.ExtensionState.ENABLED) { - this._sendMarginsToExtension(extension); - return; - } - // if the extension is being disabled, we must do a full refresh, - // because if there were other extensions originally - // loaded after that extension, those extensions will be disabled - // and enabled again without notification - this._changedMargins(); - }); - } - - /** - * Sets or updates the top, bottom, left and right margins for a - * monitor. Values are measured from the monitor border (and NOT from - * the workspace border). - * - * @param {int} monitor Monitor number to which set the margins. - * A negative value means "the primary monitor". - * @param {int} top Top margin in pixels - * @param {int} bottom Bottom margin in pixels - * @param {int} left Left margin in pixels - * @param {int} right Right margin in pixels - */ - setMargins(monitor, top, bottom, left, right) { - this._margins[monitor] = { - top, - bottom, - left, - right, - }; - this._changedMargins(); - } - - /** - * Clears the current margins. Must be called before configuring the monitors - * margins with setMargins(). - */ - resetMargins() { - this._margins = {}; - this._changedMargins(); - } - - /** - * Disconnects all the signals and removes the margins. - */ - destroy() { - if (this._emID) { - this._extensionManager.disconnect(this._emID); - this._emID = 0; - } - if (this._timedMarginsID) { - GLib.source_remove(this._timedMarginsID); - this._timedMarginsID = 0; - } - this._margins = null; - this._changedMargins(); - } - - _changedMargins() { - if (this._timedMarginsID) - GLib.source_remove(this._timedMarginsID); - - this._timedMarginsID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { - this._sendMarginsToAll(); - this._timedMarginsID = 0; - return GLib.SOURCE_REMOVE; - }); - } - - _sendMarginsToAll() { - this._extensionManager.getUuids().forEach(uuid => - this._sendMarginsToExtension(this._extensionManager.lookup(uuid))); - } - - _sendMarginsToExtension(extension) { - // check that the extension is an extension that has the logic to accept - // working margins - if (extension?.state !== ExtensionUtils.ExtensionState.ENABLED) - return; - - const usableArea = extension?.stateObj?.DesktopIconsUsableArea; - if (usableArea?.uuid === IDENTIFIER_UUID) { - usableArea.setMarginsForExtension( - this._UUID, this._margins); - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/docking.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/docking.js deleted file mode 100755 index 23ffd34a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/docking.js +++ /dev/null @@ -1,2679 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Clutter, - GLib, - Gio, - GObject, - Meta, - Shell, - St, -} from './dependencies/gi.js'; - -import { - AppDisplay, - Layout, - Main, - Overview, - OverviewControls, - PointerWatcher, - Workspace, - WorkspacesView, - WorkspaceSwitcherPopup, -} from './dependencies/shell/ui.js'; - -import { - AnimationUtils, -} from './dependencies/shell/misc.js'; - -import { - AppSpread, - DockDash, - DesktopIconsIntegration, - FileManager1API, - Intellihide, - LauncherAPI, - Locations, - NotificationsMonitor, - Theming, - Utils, -} from './imports.js'; - -const {signals: Signals} = imports; - -const DOCK_DWELL_CHECK_INTERVAL = 100; -const ICON_ANIMATOR_DURATION = 3000; -const STARTUP_ANIMATION_TIME = 500; - -export const State = Object.freeze({ - HIDDEN: 0, - SHOWING: 1, - SHOWN: 2, - HIDING: 3, -}); - -const scrollAction = Object.freeze({ - DO_NOTHING: 0, - CYCLE_WINDOWS: 1, - SWITCH_WORKSPACE: 2, -}); - -const Labels = Object.freeze({ - INITIALIZE: Symbol('initialize'), - ISOLATION: Symbol('isolation'), - LOCATIONS: Symbol('locations'), - MAIN_DASH: Symbol('main-dash'), - OLD_DASH_CHANGES: Symbol('old-dash-changes'), - SETTINGS: Symbol('settings'), - STARTUP_ANIMATION: Symbol('startup-animation'), - WORKSPACE_SWITCH_SCROLL: Symbol('workspace-switch-scroll'), -}); - -/** - * A simple St.Widget with one child whose allocation takes into account the - * slide out of its child via the slide-x property ([0:1]). - * - * Required since I want to track the input region of this container which is - * based on its allocation even if the child overlows the parent actor. By doing - * this the region of the dash that is slideout is not steling anymore the input - * regions making the extesion usable when the primary monitor is the right one. - * - * The slide-x parameter can be used to directly animate the sliding. The parent - * must have a WEST (SOUTH) anchor_point to achieve the sliding to the RIGHT (BOTTOM) - * side. - */ -const DashSlideContainer = GObject.registerClass({ - Properties: { - 'monitor-index': GObject.ParamSpec.uint( - 'monitor-index', 'monitor-index', 'monitor-index', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - 0, GLib.MAXUINT32, 0), - 'side': GObject.ParamSpec.enum( - 'side', 'side', 'side', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - St.Side, St.Side.LEFT), - 'slide-x': GObject.ParamSpec.double( - 'slide-x', 'slide-x', 'slide-x', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, - 0, 1, 1), - }, -}, class DashSlideContainer extends St.Bin { - _init(params = {}) { - super._init(params); - - this._slideoutSize = 0; // minimum size when slided out - this.connect('notify::slide-x', () => this.queue_relayout()); - - if (this.side === St.Side.TOP && DockManager.settings.dockFixed) { - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - this._signalsHandler.add(Main.panel, 'notify::height', - () => this.queue_relayout()); - } - } - - vfunc_allocate(box) { - const contentBox = this.get_theme_node().get_content_box(box); - - this.set_allocation(box); - - if (!this.child) - return; - - const availWidth = contentBox.x2 - contentBox.x1; - let availHeight = contentBox.y2 - contentBox.y1; - const [, , natChildWidth, natChildHeight] = - this.child.get_preferred_size(); - - const childWidth = natChildWidth; - const childHeight = natChildHeight; - - const childBox = new Clutter.ActorBox(); - - const slideoutSize = this._slideoutSize; - - if (this.side === St.Side.LEFT) { - childBox.x1 = (this.slideX - 1) * (childWidth - slideoutSize); - childBox.x2 = slideoutSize + this.slideX * (childWidth - slideoutSize); - childBox.y1 = 0; - childBox.y2 = childBox.y1 + childHeight; - } else if ((this.side === St.Side.RIGHT) || (this.side === St.Side.BOTTOM)) { - childBox.x1 = 0; - childBox.x2 = childWidth; - childBox.y1 = 0; - childBox.y2 = childBox.y1 + childHeight; - } else if (this.side === St.Side.TOP) { - const monitor = Main.layoutManager.monitors[this.monitorIndex]; - let yOffset = 0; - if (Main.panel.x === monitor.x && Main.panel.y === monitor.y && - DockManager.settings.dockFixed) - yOffset = Main.panel.height; - childBox.x1 = 0; - childBox.x2 = childWidth; - childBox.y1 = (this.slideX - 1) * (childHeight - slideoutSize) + yOffset; - childBox.y2 = slideoutSize + this.slideX * (childHeight - slideoutSize) + yOffset; - availHeight += yOffset; - } - - this.child.allocate(childBox); - - this.child.set_clip(-childBox.x1, -childBox.y1, - -childBox.x1 + availWidth, -childBox.y1 + availHeight); - } - - /** - * Just the child width but taking into account the slided out part - * - * @param forHeight - */ - vfunc_get_preferred_width(forHeight) { - let [minWidth, natWidth] = super.vfunc_get_preferred_width(forHeight || 0); - if ((this.side === St.Side.LEFT) || (this.side === St.Side.RIGHT)) { - minWidth = (minWidth - this._slideoutSize) * this.slideX + this._slideoutSize; - natWidth = (natWidth - this._slideoutSize) * this.slideX + this._slideoutSize; - } - return [minWidth, natWidth]; - } - - /** - * Just the child height but taking into account the slided out part - * - * @param forWidth - */ - vfunc_get_preferred_height(forWidth) { - let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth || 0); - if ((this.side === St.Side.TOP) || (this.side === St.Side.BOTTOM)) { - minHeight = (minHeight - this._slideoutSize) * this.slideX + this._slideoutSize; - natHeight = (natHeight - this._slideoutSize) * this.slideX + this._slideoutSize; - - if (this.side === St.Side.TOP && DockManager.settings.dockFixed) { - const monitor = Main.layoutManager.monitors[this.monitorIndex]; - if (Main.panel.x === monitor.x && Main.panel.y === monitor.y) { - minHeight += Main.panel.height; - natHeight += Main.panel.height; - } - } - } - return [minHeight, natHeight]; - } -}); - -const DockedDash = GObject.registerClass({ - Properties: { - 'is-main': GObject.ParamSpec.boolean( - 'is-main', 'is-main', 'is-main', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - false), - 'monitor-index': GObject.ParamSpec.uint( - 'monitor-index', 'monitor-index', 'monitor-index', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - 0, GLib.MAXUINT32, 0), - }, - Signals: { - 'showing': {}, - 'hiding': {}, - }, -}, class DashToDock extends St.Bin { - _init(params) { - this._position = Utils.getPosition(); - - // This is the centering actor - super._init({ - ...params, - name: 'dashtodockContainer', - reactive: false, - style_class: Theming.PositionStyleClass[this._position], - }); - - if (this.monitorIndex === undefined) { - // Hello turkish locale, gjs has instead defined this.monitorİndex - // See: https://gitlab.gnome.org/GNOME/gjs/-/merge_requests/742 - this.monitorIndex = this.monitor_index; - } - - this._rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL; - - // Load settings - const {settings} = DockManager; - this._isHorizontal = (this._position === St.Side.TOP) || (this._position === St.Side.BOTTOM); - - // Temporary ignore hover events linked to autohide for whatever reason - this._ignoreHover = false; - this._oldignoreHover = null; - // This variables are linked to the settings regardles of autohide or intellihide - // being temporary disable. Get set by _updateVisibilityMode; - this._autohideIsEnabled = null; - this._intellihideIsEnabled = null; - - // This variable marks if Meta.disable_unredirect_for_display() is called - // to help restore the original state when intelihide is disabled. - this._unredirectDisabled = false; - - // Create intellihide object to monitor windows overlapping - this._intellihide = new Intellihide.Intellihide(this.monitorIndex); - - // initialize dock state - this._dockState = State.HIDDEN; - - // Put dock on the required monitor - this._monitor = Main.layoutManager.monitors[this.monitorIndex]; - - // this store size and the position where the dash is shown; - // used by intellihide module to check window overlap. - this.staticBox = new Clutter.ActorBox(); - - // Initialize pressure barrier variables - this._canUsePressure = false; - this._pressureBarrier = null; - this._barrier = null; - this._removeBarrierTimeoutId = 0; - - // Initialize dwelling system variables - this._dockDwelling = false; - this._dockWatch = null; - this._dockDwellUserTime = 0; - this._dockDwellTimeoutId = 0; - - // Create a new dash object - this.dash = new DockDash.DockDash(this.monitorIndex); - - if (Main.overview.isDummy || !settings.showShowAppsButton) - this.dash.hideShowAppsButton(); - - // Create the containers for sliding in and out and - // centering, turn on track hover - // This is the sliding actor whose allocation is to be tracked for input regions - this._slider = new DashSlideContainer({ - monitor_index: this._monitor.index, - side: this._position, - slide_x: Main.layoutManager._startingUp ? 0 : 1, - ...this._isHorizontal ? { - x_align: Clutter.ActorAlign.CENTER, - } : { - y_align: Clutter.ActorAlign.CENTER, - }, - }); - - // This is the actor whose hover status us tracked for autohide - this._box = new St.BoxLayout({ - name: 'dashtodockBox', - reactive: true, - track_hover: true, - }); - this._box.connect('notify::hover', this._hoverChanged.bind(this)); - - // Connect global signals - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - this._bindSettingsChanges(); - this._signalsHandler.add([ - // update when workarea changes, for instance if other extensions modify the struts - // (like moving th panel at the bottom) - global.display, - 'workareas-changed', - this._resetPosition.bind(this), - ], [ - global.display, - 'in-fullscreen-changed', - this._updateBarrier.bind(this), - ], [ - // Monitor windows overlapping - this._intellihide, - 'status-changed', - this._updateDashVisibility.bind(this), - ], [ - this.dash, - 'menu-opened', - () => { - this._onMenuOpened(); - }, - ], [ - // sync hover after a popupmenu is closed - this.dash, - 'menu-closed', - () => { - this._onMenuClosed(); - }, - ], [ - this.dash, - 'notify::requires-visibility', - () => this._updateDashVisibility(), - ]); - - if (!Main.overview.isDummy) { - this._signalsHandler.add([ - Main.overview, - 'item-drag-begin', - this._onDragStart.bind(this), - ], [ - Main.overview, - 'item-drag-end', - this._onDragEnd.bind(this), - ], [ - Main.overview, - 'item-drag-cancelled', - this._onDragEnd.bind(this), - ], [ - Main.overview, - 'showing', - this._onOverviewShowing.bind(this), - ], [ - Main.overview, - 'hiding', - this._onOverviewHiding.bind(this), - ], - [ - Main.overview, - 'hidden', - this._onOverviewHidden.bind(this), - ]); - } - - this._themeManager = new Theming.ThemeManager(this); - this._signalsHandler.add(this._themeManager, 'updated', - () => this.dash.resetAppIcons()); - - this._signalsHandler.add(DockManager.iconTheme, 'changed', - () => this.dash.resetAppIcons()); - - // Since the actor is not a topLevel child and its parent is now not added to the Chrome, - // the allocation change of the parent container (slide in and slideout) doesn't trigger - // anymore an update of the input regions. Force the update manually. - this.connect('notify::allocation', - Main.layoutManager._queueUpdateRegions.bind(Main.layoutManager)); - - - // Since Clutter has no longer ClutterAllocationFlags, - // "allocation-changed" signal has been removed. MR !1245 - this.dash._container.connect('notify::allocation', this._updateStaticBox.bind(this)); - this._slider.connect(this._isHorizontal ? 'notify::x' : 'notify::y', - this._updateStaticBox.bind(this)); - - // Load optional features that need to be activated for one dock only - if (this.isMain) - this._enableExtraFeatures(); - // Load optional features that need to be activated once per dock - this._optionalScrollWorkspaceSwitch(); - - // Delay operations that require the shell to be fully loaded and with - // user theme applied. - - this._signalsHandler.addWithLabel(Labels.INITIALIZE, global.stage, - 'after-paint', () => this._initialize()); - - // Add dash container actor and the container to the Chrome. - this.set_child(this._slider); - this._slider.set_child(this._box); - this._box.add_child(this.dash); - - // Add aligning container without tracking it for input region - this._trackDock(); - - // Create and apply height/width constraint to the dash. - if (this._isHorizontal) { - this.connect('notify::width', () => { - this.dash.setMaxSize(this.width, this.height); - }); - } else { - this.connect('notify::height', () => { - this.dash.setMaxSize(this.width, this.height); - }); - } - - if (this._position === St.Side.RIGHT) { - this.connect('notify::width', () => - (this.translation_x = -this.width)); - } else if (this._position === St.Side.BOTTOM) { - this.connect('notify::height', () => - (this.translation_y = -this.height)); - } - - // Set initial position - this._resetPosition(); - - this.connect('destroy', this._onDestroy.bind(this)); - } - - get position() { - return this._position; - } - - get isHorizontal() { - return this._isHorizontal; - } - - _untrackDock() { - Main.layoutManager.untrackChrome(this); - } - - _trackDock() { - if (DockManager.settings.dockFixed) { - Main.layoutManager.addChrome(this, { - trackFullscreen: true, - affectsStruts: true, - }); - } else { - Main.layoutManager.addChrome(this); - } - } - - _initialize() { - this._signalsHandler.removeWithLabel(Labels.INITIALIZE); - - // Apply custome css class according to the settings - this._themeManager.updateCustomTheme(); - - this._updateVisibilityMode(); - - // In case we are already inside the overview when the extension is loaded, - // for instance on unlocking the screen if it was locked with the overview open. - if (Main.overview.visibleTarget) - this._onOverviewShowing(); - - this._updateAutoHideBarriers(); - } - - _onDestroy() { - // The dash, intellihide and themeManager have global signals as well internally - this.dash.destroy(); - this._intellihide.destroy(); - this._themeManager.destroy(); - - if (this._marginLater) { - Utils.laterRemove(this._marginLater); - delete this._marginLater; - } - - if (this._triggerTimeoutId) - GLib.source_remove(this._triggerTimeoutId); - - this._restoreUnredirect(); - - // Remove barrier timeout - if (this._removeBarrierTimeoutId > 0) - GLib.source_remove(this._removeBarrierTimeoutId); - - // Remove existing barrier - this._removeBarrier(); - - // Remove pointer watcher - if (this._dockWatch) { - PointerWatcher.getPointerWatcher()._removeWatch(this._dockWatch); - this._dockWatch = null; - } - } - - _updateAutoHideBarriers() { - // Remove pointer watcher - if (this._dockWatch) { - PointerWatcher.getPointerWatcher()._removeWatch(this._dockWatch); - this._dockWatch = null; - } - - // Setup pressure barrier (GS38+ only) - this._updatePressureBarrier(); - this._updateBarrier(); - - // setup dwelling system if pressure barriers are not available - this._setupDockDwellIfNeeded(); - } - - _bindSettingsChanges() { - const {settings} = DockManager; - this._signalsHandler.add([ - settings, - 'changed::scroll-action', - () => { - this._optionalScrollWorkspaceSwitch(); - }, - ], [ - settings, - 'changed::dash-max-icon-size', - () => { - this.dash.setIconSize(settings.dashMaxIconSize); - }, - ], [ - settings, - 'changed::icon-size-fixed', - () => { - this.dash.setIconSize(settings.dashMaxIconSize); - }, - ], [ - settings, - 'changed::show-favorites', - () => { - this.dash.resetAppIcons(); - }, - ], [ - settings, - 'changed::show-trash', - () => { - this.dash.resetAppIcons(); - }, - Utils.SignalsHandlerFlags.CONNECT_AFTER, - ], [ - settings, - 'changed::show-mounts', - () => { - this.dash.resetAppIcons(); - }, - Utils.SignalsHandlerFlags.CONNECT_AFTER, - ], [ - settings, - 'changed::isolate-locations', - () => this.dash.resetAppIcons(), - Utils.SignalsHandlerFlags.CONNECT_AFTER, - ], [ - settings, - 'changed::dance-urgent-applications', - () => this.dash.resetAppIcons(), - Utils.SignalsHandlerFlags.CONNECT_AFTER, - ], [ - settings, - 'changed::show-running', - () => { - this.dash.resetAppIcons(); - }, - ], [ - settings, - 'changed::show-apps-always-in-the-edge', - () => { - this.dash.updateShowAppsButton(); - }, - ], [ - settings, - 'changed::show-apps-at-top', - () => { - this.dash.updateShowAppsButton(); - }, - ], [ - settings, - 'changed::show-show-apps-button', - () => { - if (!Main.overview.isDummy && - settings.showShowAppsButton) - this.dash.showShowAppsButton(); - else - this.dash.hideShowAppsButton(); - }, - ], [ - settings, - 'changed::dock-fixed', - () => { - this._untrackDock(); - this._trackDock(); - - this._resetPosition(); - this._updateAutoHideBarriers(); - this._updateVisibilityMode(); - }, - ], [ - settings, - 'changed::manualhide', - () => { - this._updateVisibilityMode(); - }, - ], [ - settings, - 'changed::intellihide', - () => { - this._updateVisibilityMode(); - this._updateVisibleDesktop(); - }, - ], [ - settings, - 'changed::intellihide-mode', - () => { - this._intellihide.forceUpdate(); - }, - ], [ - settings, - 'changed::autohide', - () => { - this._updateVisibilityMode(); - this._updateAutoHideBarriers(); - }, - ], [ - settings, - 'changed::autohide-in-fullscreen', - this._updateBarrier.bind(this), - ], [ - settings, - 'changed::show-dock-urgent-notify', - () => { - this.dash.resetAppIcons(); - }, - ], - [ - settings, - 'changed::extend-height', - this._resetPosition.bind(this), - ], [ - settings, - 'changed::height-fraction', - this._resetPosition.bind(this), - ], [ - settings, - 'changed::always-center-icons', - () => this.dash.resetAppIcons(), - ], [ - settings, - 'changed::require-pressure-to-show', - () => this._updateAutoHideBarriers(), - ], [ - settings, - 'changed::pressure-threshold', - () => { - this._updatePressureBarrier(); - this._updateBarrier(); - }, - ]); - } - - _restoreUnredirect() { - if (this._unredirectDisabled) { - Meta.enable_unredirect_for_display(global.display); - this._unredirectDisabled = false; - } - } - - /** - * This is call when visibility settings change - */ - _updateVisibilityMode() { - const {settings} = DockManager; - if (DockManager.settings.dockFixed || DockManager.settings.manualhide) { - this._autohideIsEnabled = false; - this._intellihideIsEnabled = false; - } else { - this._autohideIsEnabled = settings.autohide; - this._intellihideIsEnabled = settings.intellihide; - } - - if (this._autohideIsEnabled) - this.add_style_class_name('autohide'); - else - this.remove_style_class_name('autohide'); - - if (this._intellihideIsEnabled) { - this._intellihide.enable(); - } else { - this._intellihide.disable(); - this._restoreUnredirect(); - } - - this._updateDashVisibility(); - } - - /** - * Show/hide dash based on, in order of priority: - * overview visibility - * fixed mode - * intellihide - * autohide - * overview visibility - */ - _updateDashVisibility() { - if (DockManager.settings.manualhide) { - this._ignoreHover = true; - this._removeAnimations(); - this._animateOut(0, 0); - return; - } - - if (Main.overview.visibleTarget) - return; - - const {settings} = DockManager; - - if (DockManager.settings.dockFixed) { - this._removeAnimations(); - this._animateIn(settings.animationTime, 0); - } else if (this._intellihideIsEnabled) { - if (!this.dash.requiresVisibility && this._intellihide.getOverlapStatus()) { - this._ignoreHover = false; - // Do not hide if autohide is enabled and mouse is hover - if (!this._box.hover || !this._autohideIsEnabled) - this._animateOut(settings.animationTime, 0); - } else { - this._ignoreHover = true; - this._removeAnimations(); - this._animateIn(settings.animationTime, 0); - } - } else if (this._autohideIsEnabled) { - this._ignoreHover = false; - - if (this._box.hover || this.dash.requiresVisibility) - this._animateIn(settings.animationTime, 0); - else - this._animateOut(settings.animationTime, 0); - } else { - this._animateOut(settings.animationTime, 0); - } - } - - _onOverviewShowing() { - this.add_style_class_name('overview'); - - this._ignoreHover = true; - this._intellihide.disable(); - this._removeAnimations(); - this._animateIn(DockManager.settings.animationTime, 0); - } - - _onOverviewHiding() { - this._intellihide.enable(); - this._updateDashVisibility(); - } - - _onOverviewHidden() { - this.remove_style_class_name('overview'); - this._updateDashVisibility(); - } - - _onMenuOpened() { - this._ignoreHover = true; - } - - _onMenuClosed() { - this._ignoreHover = false; - this._box.sync_hover(); - this._updateDashVisibility(); - } - - _hoverChanged() { - if (!this._ignoreHover) { - // Skip if dock is not in autohide mode for instance because it is shown - // by intellihide. - if (this._autohideIsEnabled) { - if (this._box.hover || Main.overview.visible) - this._show(); - else - this._hide(); - } - } - } - - getDockState() { - return this._dockState; - } - - _show() { - this._delayedHide = false; - if ((this._dockState === State.HIDDEN) || (this._dockState === State.HIDING)) { - if (this._dockState === State.HIDING) - // suppress all potential queued transitions - i.e. added but not started, - // always give priority to show - this._removeAnimations(); - - this.emit('showing'); - this._animateIn(DockManager.settings.animationTime, 0); - } - } - - _hide() { - // If no hiding animation is running or queued - if ((this._dockState === State.SHOWN) || (this._dockState === State.SHOWING)) { - const {settings} = DockManager; - const delay = settings.hideDelay; - - if (this._dockState === State.SHOWING) { - // if a show already started, let it finish; queue hide without removing the show. - // to obtain this, we wait for the animateIn animation to be completed - this._delayedHide = true; - return; - } - - this.emit('hiding'); - this._animateOut(settings.animationTime, delay); - } - } - - _animateIn(time, delay) { - if (!this._unredirectDisabled && this._intellihideIsEnabled) { - Meta.disable_unredirect_for_display(global.display); - this._unredirectDisabled = true; - } - this._dockState = State.SHOWING; - this.dash.iconAnimator.start(); - this._delayedHide = false; - - this._slider.ease_property('slide-x', 1, { - duration: time * 1000, - delay: delay * 1000, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - this._dockState = State.SHOWN; - // Remove barrier so that mouse pointer is released and can - // monitors on other side of dock. - // NOTE: Delay needed to keep mouse from moving past dock and - // re-hiding dock immediately. This gives users an opportunity - // to hover over the dock - if (this._removeBarrierTimeoutId > 0) - GLib.source_remove(this._removeBarrierTimeoutId); - - if (!this._delayedHide) { - this._removeBarrierTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, 100, this._removeBarrier.bind(this)); - } else { - this._hide(); - } - }, - }); - } - - _animateOut(time, delay) { - this._dockState = State.HIDING; - - this._slider.ease_property('slide-x', 0, { - duration: time * 1000, - delay: delay * 1000, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - this._dockState = State.HIDDEN; - if (this._intellihideIsEnabled && this._unredirectDisabled) { - Meta.enable_unredirect_for_display(global.display); - this._unredirectDisabled = false; - } - // Remove queued barried removal if any - if (this._removeBarrierTimeoutId > 0) - GLib.source_remove(this._removeBarrierTimeoutId); - this._updateBarrier(); - this.dash.iconAnimator.pause(); - }, - }); - } - - /** - * Dwelling system based on the GNOME Shell 3.14 messageTray code. - */ - _setupDockDwellIfNeeded() { - // If we don't have extended barrier features, then we need - // to support the old tray dwelling mechanism. - if (this._autohideIsEnabled && - (!Utils.supportsExtendedBarriers() || - !DockManager.settings.requirePressureToShow)) { - const pointerWatcher = PointerWatcher.getPointerWatcher(); - this._dockWatch = pointerWatcher.addWatch( - DOCK_DWELL_CHECK_INTERVAL, this._checkDockDwell.bind(this)); - this._dockDwelling = false; - this._dockDwellUserTime = 0; - } - } - - _checkDockDwell(x, y) { - const workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitor.index); - let shouldDwell; - // Check for the correct screen edge, extending the sensitive area to the whole workarea, - // minus 1 px to avoid conflicting with other active corners. - if (this._position === St.Side.LEFT) { - shouldDwell = (x === this._monitor.x) && (y > workArea.y) && - (y < workArea.y + workArea.height); - } else if (this._position === St.Side.RIGHT) { - shouldDwell = (x === this._monitor.x + this._monitor.width - 1) && - (y > workArea.y) && (y < workArea.y + workArea.height); - } else if (this._position === St.Side.TOP) { - shouldDwell = (y === this._monitor.y) && (x > workArea.x) && - (x < workArea.x + workArea.width); - } else if (this._position === St.Side.BOTTOM) { - shouldDwell = (y === this._monitor.y + this._monitor.height - 1) && - (x > workArea.x) && (x < workArea.x + workArea.width); - } - - if (shouldDwell) { - // We only set up dwell timeout when the user is not hovering over the dock - // already (!this._box.hover). - // The _dockDwelling variable is used so that we only try to - // fire off one dock dwell - if it fails (because, say, the user has the mouse down), - // we don't try again until the user moves the mouse up and down again. - if (!this._dockDwelling && !this._box.hover && (this._dockDwellTimeoutId === 0)) { - // Save the interaction timestamp so we can detect user input - const focusWindow = global.display.focus_window; - this._dockDwellUserTime = focusWindow ? focusWindow.user_time : 0; - - this._dockDwellTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - DockManager.settings.showDelay * 1000, - this._dockDwellTimeout.bind(this)); - GLib.Source.set_name_by_id(this._dockDwellTimeoutId, - '[dash-to-dock] this._dockDwellTimeout'); - } - this._dockDwelling = true; - } else { - this._cancelDockDwell(); - this._dockDwelling = false; - } - } - - _cancelDockDwell() { - if (this._dockDwellTimeoutId !== 0) { - GLib.source_remove(this._dockDwellTimeoutId); - this._dockDwellTimeoutId = 0; - } - } - - _dockDwellTimeout() { - this._dockDwellTimeoutId = 0; - - if (!DockManager.settings.autohideInFullscreen && - this._monitor.inFullscreen) - return GLib.SOURCE_REMOVE; - - // We don't want to open the tray when a modal dialog - // is up, so we check the modal count for that. When we are in the - // overview we have to take the overview's modal push into account - if (Main.modalCount > (Main.overview.visible ? 1 : 0)) - return GLib.SOURCE_REMOVE; - - // If the user interacted with the focus window since we started the tray - // dwell (by clicking or typing), don't activate the message tray - const focusWindow = global.display.focus_window; - const currentUserTime = focusWindow ? focusWindow.user_time : 0; - if (currentUserTime !== this._dockDwellUserTime) - return GLib.SOURCE_REMOVE; - - // Reuse the pressure version function, the logic is the same - this._onPressureSensed(); - return GLib.SOURCE_REMOVE; - } - - _updatePressureBarrier() { - const {settings} = DockManager; - this._canUsePressure = Utils.supportsExtendedBarriers(); - const {pressureThreshold} = settings; - - // Remove existing pressure barrier - if (this._pressureBarrier) { - this._pressureBarrier.destroy(); - this._pressureBarrier = null; - } - - if (this._barrier) { - this._barrier.destroy(); - this._barrier = null; - } - - // Create new pressure barrier based on pressure threshold setting - if (this._canUsePressure && this._autohideIsEnabled && - DockManager.settings.requirePressureToShow) { - this._pressureBarrier = new Layout.PressureBarrier( - pressureThreshold, settings.showDelay * 1000, - Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW); - this._pressureBarrier.connect('trigger', _barrier => { - if (!settings.autohideInFullscreen && this._monitor.inFullscreen) - return; - this._onPressureSensed(); - }); - } - } - - /** - * handler for mouse pressure sensed - */ - _onPressureSensed() { - if (Main.overview.visibleTarget) - return; - - if (this._triggerTimeoutId) - GLib.source_remove(this._triggerTimeoutId); - - // In case the mouse move away from the dock area before hovering it, - // in such case the leave event would never be triggered and the dock - // would stay visible forever. - this._triggerTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { - const [x, y, mods_] = global.get_pointer(); - let shouldHide = true; - switch (this._position) { - case St.Side.LEFT: - if (x <= this.staticBox.x2 && - x >= this._monitor.x && - y >= this._monitor.y && - y <= this._monitor.y + this._monitor.height) - shouldHide = false; - - break; - case St.Side.RIGHT: - if (x >= this.staticBox.x1 && - x <= this._monitor.x + this._monitor.width && - y >= this._monitor.y && - y <= this._monitor.y + this._monitor.height) - shouldHide = false; - - break; - case St.Side.TOP: - if (x >= this._monitor.x && - x <= this._monitor.x + this._monitor.width && - y <= this.staticBox.y2 && - y >= this._monitor.y) - shouldHide = false; - - break; - case St.Side.BOTTOM: - if (x >= this._monitor.x && - x <= this._monitor.x + this._monitor.width && - y >= this.staticBox.y1 && - y <= this._monitor.y + this._monitor.height) - shouldHide = false; - } - if (shouldHide) { - this._triggerTimeoutId = 0; - this._hoverChanged(); - return GLib.SOURCE_REMOVE; - } else { - return GLib.SOURCE_CONTINUE; - } - }); - - this._show(); - } - - /** - * Remove pressure barrier - */ - _removeBarrier() { - if (this._barrier) { - if (this._pressureBarrier) - this._pressureBarrier.removeBarrier(this._barrier); - this._barrier.destroy(); - this._barrier = null; - } - this._removeBarrierTimeoutId = 0; - return false; - } - - /** - * Update pressure barrier size - */ - _updateBarrier() { - // Remove existing barrier - this._removeBarrier(); - - // The barrier needs to be removed in fullscreen with autohide disabled - // otherwise the mouse can get trapped on monitor. - if (this._monitor.inFullscreen && - !DockManager.settings.autohideInFullscreen) - return; - - // Manually reset pressure barrier - // This is necessary because we remove the pressure barrier when it is - // triggered to show the dock - if (this._pressureBarrier) { - this._pressureBarrier._reset(); - this._pressureBarrier._isTriggered = false; - } - - // Create new barrier - // The barrier extends to the whole workarea, minus 1 px to avoid - // conflicting with other active corners - // Note: dash in fixed position doesn't use pressure barrier. - if (this._canUsePressure && this._autohideIsEnabled && - DockManager.settings.requirePressureToShow) { - let x1, x2, y1, y2, direction; - const workArea = Main.layoutManager.getWorkAreaForMonitor( - this._monitor.index); - - if (this._position === St.Side.LEFT) { - x1 = this._monitor.x + 1; - x2 = x1; - y1 = workArea.y + 1; - y2 = workArea.y + workArea.height - 1; - direction = Meta.BarrierDirection.POSITIVE_X; - } else if (this._position === St.Side.RIGHT) { - x1 = this._monitor.x + this._monitor.width - 1; - x2 = x1; - y1 = workArea.y + 1; - y2 = workArea.y + workArea.height - 1; - direction = Meta.BarrierDirection.NEGATIVE_X; - } else if (this._position === St.Side.TOP) { - x1 = workArea.x + 1; - x2 = workArea.x + workArea.width - 1; - y1 = this._monitor.y; - y2 = y1; - direction = Meta.BarrierDirection.POSITIVE_Y; - } else if (this._position === St.Side.BOTTOM) { - x1 = workArea.x + 1; - x2 = workArea.x + workArea.width - 1; - y1 = this._monitor.y + this._monitor.height; - y2 = y1; - direction = Meta.BarrierDirection.NEGATIVE_Y; - } - - if (this._pressureBarrier && this._dockState === State.HIDDEN) { - this._barrier = new Meta.Barrier({ - backend: global.backend, - x1, - x2, - y1, - y2, - directions: direction, - }); - this._pressureBarrier.addBarrier(this._barrier); - } - } - } - - _isPrimaryMonitor() { - return this.monitorIndex === Main.layoutManager.primaryIndex; - } - - _resetPosition() { - // Ensure variables linked to settings are updated. - this._updateVisibilityMode(); - - const {dockFixed: fixedIsEnabled, dockExtended: extendHeight} = DockManager.settings; - - if (fixedIsEnabled) - this.add_style_class_name('fixed'); - else - this.remove_style_class_name('fixed'); - - // Note: do not use the workarea coordinates in the direction on which the dock is placed, - // to avoid a loop [position change -> workArea change -> position change] with - // fixed dock. - const workArea = Main.layoutManager.getWorkAreaForMonitor(this.monitorIndex); - - let fraction = DockManager.settings.heightFraction; - if (extendHeight) - fraction = 1; - else if ((fraction < 0) || (fraction > 1)) - fraction = 0.95; - - if (this._isHorizontal) { - this.width = Math.round(fraction * workArea.width); - - let posY = this._monitor.y; - if (this._position === St.Side.BOTTOM) - posY += this._monitor.height; - - this.x = workArea.x + Math.round((1 - fraction) / 2 * workArea.width); - this.y = posY; - - if (extendHeight) { - this.dash._container.set_width(this.width); - this.add_style_class_name('extended'); - } else { - this.dash._container.set_width(-1); - this.remove_style_class_name('extended'); - } - } else { - this.height = Math.round(fraction * workArea.height); - - let posX = this._monitor.x; - if (this._position === St.Side.RIGHT) - posX += this._monitor.width; - - this.x = posX; - this.y = workArea.y + Math.round((1 - fraction) / 2 * workArea.height); - - if (extendHeight) { - this.dash._container.set_height(this.height); - this.add_style_class_name('extended'); - } else { - this.dash._container.set_height(-1); - this.remove_style_class_name('extended'); - } - } - } - - _updateVisibleDesktop() { - if (!this._intellihideIsEnabled) - return; - - const {desktopIconsUsableArea} = DockManager.getDefault(); - if (this._position === St.Side.BOTTOM) - desktopIconsUsableArea.setMargins(this.monitorIndex, 0, this._box.height, 0, 0); - else if (this._position === St.Side.TOP) - desktopIconsUsableArea.setMargins(this.monitorIndex, this._box.height, 0, 0, 0); - else if (this._position === St.Side.RIGHT) - desktopIconsUsableArea.setMargins(this.monitorIndex, 0, 0, 0, this._box.width); - else if (this._position === St.Side.LEFT) - desktopIconsUsableArea.setMargins(this.monitorIndex, 0, 0, this._box.width, 0); - } - - _updateStaticBox() { - this.staticBox.init_rect( - this.x + this._slider.x - (this._position === St.Side.RIGHT ? this._box.width : 0), - this.y + this._slider.y - (this._position === St.Side.BOTTOM ? this._box.height : 0), - this._box.width, - this._box.height - ); - - this._intellihide.updateTargetBox(this.staticBox); - this._updateVisibleDesktop(); - } - - _removeAnimations() { - this._slider.remove_all_transitions(); - } - - _onDragStart() { - this._oldignoreHover = this._ignoreHover; - this._ignoreHover = true; - this._animateIn(DockManager.settings.animationTime, 0); - } - - _onDragEnd() { - if (this._oldignoreHover) - this._ignoreHover = this._oldignoreHover; - this._oldignoreHover = null; - this._box.sync_hover(); - } - - /** - * Show dock and give key focus to it - */ - _onAccessibilityFocus() { - this._box.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); - this._animateIn(DockManager.settings.animationTime, 0); - } - - // Optional features to be enabled only for the main Dock - _enableExtraFeatures() { - // Restore dash accessibility - Main.ctrlAltTabManager.addGroup( - this.dash, _('Dash'), 'user-bookmarks-symbolic', - {focusCallback: this._onAccessibilityFocus.bind(this)}); - } - - /** - * Switch workspace by scrolling over the dock - */ - _optionalScrollWorkspaceSwitch() { - const isEnabled = () => - DockManager.settings.scrollAction === scrollAction.SWITCH_WORKSPACE; - - const enable = () => { - this._signalsHandler.removeWithLabel(Labels.WORKSPACE_SWITCH_SCROLL); - - this._signalsHandler.addWithLabel(Labels.WORKSPACE_SWITCH_SCROLL, - this._box, 'scroll-event', (_, e) => onScrollEvent(e)); - }; - - const disable = () => { - this._signalsHandler.removeWithLabel(Labels.WORKSPACE_SWITCH_SCROLL); - - if (this._optionalScrollWorkspaceSwitchDeadTimeId) { - GLib.source_remove(this._optionalScrollWorkspaceSwitchDeadTimeId); - this._optionalScrollWorkspaceSwitchDeadTimeId = 0; - } - }; - - DockManager.settings.connect('changed::scroll-action', () => { - if (isEnabled()) - enable(); - else - disable(); - }); - - if (isEnabled()) - enable(); - - // This was inspired to desktop-scroller@obsidien.github.com - const onScrollEvent = event => { - // When in overview change workspace only in windows view - if (Main.overview.visible) - return false; - - const activeWs = global.workspace_manager.get_active_workspace(); - let direction = null; - - let prevDirection, nextDirection; - if (global.workspace_manager.layout_columns > global.workspace_manager.layout_rows) { - prevDirection = Meta.MotionDirection.UP; - nextDirection = Meta.MotionDirection.DOWN; - } else { - prevDirection = Meta.MotionDirection.LEFT; - nextDirection = Meta.MotionDirection.RIGHT; - } - - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.UP: - direction = prevDirection; - break; - case Clutter.ScrollDirection.DOWN: - direction = nextDirection; - break; - case Clutter.ScrollDirection.SMOOTH: { - const [dx_, dy] = event.get_scroll_delta(); - if (dy < 0) - direction = prevDirection; - else if (dy > 0) - direction = nextDirection; - } - break; - } - - if (direction) { - // Prevent scroll events from triggering too many workspace switches - // by adding a 250ms deadtime between each scroll event. - // Usefull on laptops when using a touchpad. - - // During the deadtime do nothing - if (this._optionalScrollWorkspaceSwitchDeadTimeId) { - return false; - } else { - this._optionalScrollWorkspaceSwitchDeadTimeId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, 250, () => { - this._optionalScrollWorkspaceSwitchDeadTimeId = 0; - }); - } - - let ws; - - ws = activeWs.get_neighbor(direction); - - if (!Main.wm._workspaceSwitcherPopup) { - // Support Workspace Grid extension showing their custom - // Grid Workspace Switcher - if (global.workspace_manager.workspace_grid !== undefined) { - Main.wm._workspaceSwitcherPopup = - global.workspace_manager.workspace_grid.getWorkspaceSwitcherPopup(); - } else { - Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup(); - } - } - // Set the actor non reactive, so that it doesn't prevent the - // clicks events from reaching the dash actor. I can't see a reason - // why it should be reactive. - Main.wm._workspaceSwitcherPopup.reactive = false; - Main.wm._workspaceSwitcherPopup.connect('destroy', () => { - Main.wm._workspaceSwitcherPopup = null; - }); - - // If Workspace Grid is installed, let them handle the scroll behaviour. - if (global.workspace_manager.workspace_grid !== undefined) - ws = global.workspace_manager.workspace_grid.actionMoveWorkspace(direction); - else - Main.wm.actionMoveWorkspace(ws); - - // Do not show workspaceSwitcher in overview - if (!Main.overview.visible) - Main.wm._workspaceSwitcherPopup.display(direction, ws.index()); - - return true; - } else { - return false; - } - }; - } - - _activateApp(appIndex) { - const children = this.dash._box.get_children().filter(actor => { - return actor.child && - actor.child.app; - }); - - // Apps currently in the dash - const apps = children.map(actor => { - return actor.child; - }); - - // Activate with button = 1, i.e. same as left click - const button = 1; - if (appIndex < apps.length) - apps[appIndex].activate(button); - } -}); - -/* - * Handle keybaord shortcuts - */ -const NUM_HOTKEYS = 10; - -const KeyboardShortcuts = class DashToDockKeyboardShortcuts { - constructor() { - this._signalsHandler = new Utils.GlobalSignalsHandler(); - - this._hotKeysEnabled = false; - if (DockManager.settings.hotKeys) - this._enableHotKeys(); - - this._signalsHandler.add([ - DockManager.settings, - 'changed::hot-keys', - () => { - if (DockManager.settings.hotKeys) - this._enableHotKeys.bind(this)(); - else - this._disableHotKeys.bind(this)(); - }, - ]); - - this._optionalNumberOverlay(); - } - - destroy() { - DockManager.allDocks.forEach(dock => { - if (dock._numberOverlayTimeoutId) { - GLib.source_remove(dock._numberOverlayTimeoutId); - dock._numberOverlayTimeoutId = 0; - } - }); - - // Remove keybindings - this._disableHotKeys(); - this._disableExtraShortcut(); - this._signalsHandler.destroy(); - } - - _enableHotKeys() { - if (this._hotKeysEnabled) - return; - - // Setup keyboard bindings for dash elements - const keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-']; - const {mainDock} = DockManager.getDefault(); - keys.forEach(function (key) { - for (let i = 0; i < NUM_HOTKEYS; i++) { - const appNum = i; - Main.wm.addKeybinding(key + (i + 1), DockManager.settings, - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, - () => { - mainDock._activateApp(appNum); - this._showOverlay(); - }); - } - }, this); - - this._hotKeysEnabled = true; - } - - _disableHotKeys() { - if (!this._hotKeysEnabled) - return; - - const keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-']; - keys.forEach(key => { - for (let i = 0; i < NUM_HOTKEYS; i++) - Main.wm.removeKeybinding(key + (i + 1)); - }, this); - - this._hotKeysEnabled = false; - } - - _optionalNumberOverlay() { - const {settings} = DockManager; - this._shortcutIsSet = false; - // Enable extra shortcut if either 'overlay' or 'show-dock' are true - if (settings.hotKeys && - (settings.hotkeysOverlay || settings.hotkeysShowDock)) - this._enableExtraShortcut(); - - this._signalsHandler.add([ - settings, - 'changed::hot-keys', - this._checkHotkeysOptions.bind(this), - ], [ - settings, - 'changed::hotkeys-overlay', - this._checkHotkeysOptions.bind(this), - ], [ - settings, - 'changed::hotkeys-show-dock', - this._checkHotkeysOptions.bind(this), - ]); - } - - _checkHotkeysOptions() { - const {settings} = DockManager; - - if (settings.hotKeys && - (settings.hotkeysOverlay || settings.hotkeysShowDock)) - this._enableExtraShortcut(); - else - this._disableExtraShortcut(); - } - - _enableExtraShortcut() { - if (!this._shortcutIsSet) { - Main.wm.addKeybinding('shortcut', DockManager.settings, - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, - this._showOverlay.bind(this)); - this._shortcutIsSet = true; - } - } - - _disableExtraShortcut() { - if (this._shortcutIsSet) { - Main.wm.removeKeybinding('shortcut'); - this._shortcutIsSet = false; - } - } - - _showOverlay() { - for (const dock of DockManager.allDocks) { - if (DockManager.settings.hotkeysOverlay) - dock.dash.toggleNumberOverlay(true); - - // Restart the counting if the shortcut is pressed again - if (dock._numberOverlayTimeoutId) { - GLib.source_remove(dock._numberOverlayTimeoutId); - dock._numberOverlayTimeoutId = 0; - } - - // Hide the overlay/dock after the timeout - const timeout = DockManager.settings.shortcutTimeout * 1000; - dock._numberOverlayTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, timeout, () => { - dock._numberOverlayTimeoutId = 0; - dock.dash.toggleNumberOverlay(false); - // Hide the dock again if necessary - dock._updateDashVisibility(); - }); - - // Show the dock if it is hidden - if (DockManager.settings.hotkeysShowDock) { - const showDock = dock._intellihideIsEnabled || dock._autohideIsEnabled; - if (showDock) - dock._show(); - } - } - } -}; - -/** - * Isolate overview to open new windows for inactive apps - * Note: the future implementaion is not fully contained here. - * Some bits are around in other methods of other classes. - * This class just take care of enabling/disabling the option. - */ -const WorkspaceIsolation = class DashToDockWorkspaceIsolation { - constructor() { - const {settings} = DockManager; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._injectionsHandler = new Utils.InjectionsHandler(); - - const updateAllDocks = () => { - DockManager.allDocks.forEach(dock => - dock.dash.resetAppIcons()); - if (settings.isolateWorkspaces || - settings.isolateMonitors) - this._enable.bind(this)(); - else - this._disable.bind(this)(); - }; - this._signalsHandler.add( - [settings, 'changed::isolate-workspaces', updateAllDocks], - [settings, 'changed::workspace-agnostic-urgent-windows', updateAllDocks], - [settings, 'changed::isolate-monitors', updateAllDocks] - ); - - if (settings.isolateWorkspaces || - settings.isolateMonitors) - this._enable(); - } - - _enable() { - // ensure I never double-register/inject - // although it should never happen - this._disable(); - - DockManager.allDocks.forEach(dock => { - this._signalsHandler.addWithLabel( - Labels.ISOLATION, - [global.display, 'restacked', () => dock.dash._queueRedisplay()], - [global.display, 'window-marked-urgent', () => dock.dash._queueRedisplay()], - [global.display, 'window-demands-attention', () => dock.dash._queueRedisplay()], - [global.window_manager, 'switch-workspace', () => dock.dash._queueRedisplay()] - ); - - // This last signal is only needed for monitor isolation, as windows - // might migrate from one monitor to another without triggering 'restacked' - if (DockManager.settings.isolateMonitors) { - this._signalsHandler.addWithLabel(Labels.ISOLATION, - global.display, - 'window-entered-monitor', - dock.dash._queueRedisplay.bind(dock.dash)); - } - }, this); - - /** - * here this is the Shell.App - */ - function IsolatedOverview() { - // These lines take care of Nautilus for icons on Desktop - const activeWorkspaceIndex = - global.workspaceManager.get_active_workspace_index(); - const windows = this.get_windows().filter(w => - !w.skipTaskbar && w.get_workspace().index() === activeWorkspaceIndex); - - if (windows.length) - return Main.activateWindow(windows[0]); - return this.open_new_window(-1); - } - - this._injectionsHandler.addWithLabel(Labels.ISOLATION, - Shell.App.prototype, - 'activate', - IsolatedOverview); - } - - _disable() { - this._signalsHandler.removeWithLabel(Labels.ISOLATION); - this._injectionsHandler.removeWithLabel(Labels.ISOLATION); - } - - destroy() { - this._signalsHandler.destroy(); - this._injectionsHandler.destroy(); - } -}; - - -export class DockManager { - constructor(extension) { - if (DockManager._singleton) - throw new Error('DashToDock has been already initialized'); - DockManager._singleton = this; - this._extension = extension; - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - this._methodInjections = new Utils.InjectionsHandler(this); - this._vfuncInjections = new Utils.VFuncInjectionsHandler(this); - this._propertyInjections = new Utils.PropertyInjectionsHandler(this); - this._settings = this._extension.getSettings( - 'org.gnome.shell.extensions.dash-to-dock'); - this._appSwitcherSettings = new Gio.Settings({schema_id: 'org.gnome.shell.app-switcher'}); - this._mapSettingsValues(); - - this._iconTheme = new St.IconTheme(); - - this._desktopIconsUsableArea = new DesktopIconsIntegration.DesktopIconsUsableAreaClass(); - this._oldDash = Main.overview.isDummy ? null : Main.overview.dash; - this._discreteGpuAvailable = AppDisplay.discreteGpuAvailable; - this._appSpread = new AppSpread.AppSpread(); - this._notificationsMonitor = new NotificationsMonitor.NotificationsMonitor(); - - const needsRemoteModel = () => - !this._notificationsMonitor.dndMode && this._settings.showIconsEmblems; - if (needsRemoteModel) - this._remoteModel = new LauncherAPI.LauncherEntryRemoteModel(); - - const ensureRemoteModel = () => { - if (needsRemoteModel && !this._remoteModel) { - this._remoteModel = new LauncherAPI.LauncherEntryRemoteModel(); - } else if (!needsRemoteModel && this._remoteModel) { - this._remoteModel.destroy(); - delete this._remoteModel; - } - }; - - this._notificationsMonitor.connect('changed', ensureRemoteModel); - this._settings.connect('changed::show-icons-emblems', ensureRemoteModel); - - if (this._discreteGpuAvailable === undefined) { - const updateDiscreteGpuAvailable = () => { - const switcherooProxy = global.get_switcheroo_control(); - if (switcherooProxy) { - const prop = switcherooProxy.get_cached_property('HasDualGpu'); - this._discreteGpuAvailable = prop?.unpack() ?? false; - } else { - this._discreteGpuAvailable = false; - } - }; - this._signalsHandler.add(global, 'notify::switcheroo-control', - () => updateDiscreteGpuAvailable()); - updateDiscreteGpuAvailable(); - } - - // Connect relevant signals to the toggling function - this._bindSettingsChanges(); - - this._ensureLocations(); - - /* Array of all the docks created */ - this._allDocks = []; - this._createDocks(); - - // status variable: true when the overview is shown through the dash - // applications button. - this._forcedOverview = false; - } - - static getDefault() { - return DockManager._singleton; - } - - static get allDocks() { - return DockManager.getDefault()._allDocks; - } - - static get extension() { - return DockManager.getDefault().extension; - } - - static get settings() { - return DockManager.getDefault().settings; - } - - get extension() { - return this._extension; - } - - get settings() { - return this._settings; - } - - static get iconTheme() { - return DockManager.getDefault().iconTheme; - } - - get settings() { // eslint-disable-line no-dupe-class-members - return this._settings; - } - - get iconTheme() { - return this._iconTheme; - } - - get fm1Client() { - return this._fm1Client; - } - - get remoteModel() { - return this._remoteModel; - } - - get mainDock() { - return this._allDocks.length ? this._allDocks[0] : null; - } - - get removables() { - return this._removables; - } - - get trash() { - return this._trash; - } - - get desktopIconsUsableArea() { - return this._desktopIconsUsableArea; - } - - get discreteGpuAvailable() { - return AppDisplay.discreteGpuAvailable || this._discreteGpuAvailable; - } - - get appSpread() { - return this._appSpread; - } - - get notificationsMonitor() { - return this._notificationsMonitor; - } - - getDockByMonitor(monitorIndex) { - return this._allDocks.find(d => d.monitorIndex === monitorIndex); - } - - _ensureLocations() { - const {showMounts, showTrash} = this.settings; - - if (showTrash || showMounts) { - if (!this._fm1Client) - this._fm1Client = new FileManager1API.FileManager1Client(); - } else if (this._fm1Client) { - this._fm1Client.destroy(); - this._fm1Client = null; - } - - if (showMounts && !this._removables) { - this._removables = new Locations.Removables(); - } else if (!showMounts && this._removables) { - this._removables.destroy(); - this._removables = null; - } - - if (showTrash && !this._trash) { - this._trash = new Locations.Trash(); - } else if (!showTrash && this._trash) { - this._trash.destroy(); - this._trash = null; - } - - Locations.unWrapFileManagerApp(); - [this._methodInjections, this._propertyInjections].forEach( - injections => injections.removeWithLabel(Labels.LOCATIONS)); - - if (showMounts || showTrash) { - if (this.settings.isolateLocations) { - const fileManagerApp = Locations.wrapFileManagerApp(); - - this._methodInjections.addWithLabel(Labels.LOCATIONS, [ - Shell.AppSystem.prototype, 'get_running', - function (originalMethod, ...args) { - /* eslint-disable no-invalid-this */ - const runningApps = originalMethod.call(this, ...args); - const locationApps = Locations.getRunningApps(); - if (!locationApps.length) - return runningApps; - - const fileManagerIdx = runningApps.indexOf(fileManagerApp); - if (fileManagerIdx > -1 && fileManagerApp?.state !== Shell.AppState.RUNNING) - runningApps.splice(fileManagerIdx, 1); - - return [...runningApps, ...locationApps].sort(Utils.shellAppCompare); - /* eslint-enable no-invalid-this */ - }, - ], - [ - Shell.WindowTracker.prototype, 'get_window_app', - function (originalMethod, window) { - /* eslint-disable no-invalid-this */ - const locationApp = Locations.getRunningApps().find(a => - a.get_windows().includes(window)); - return locationApp ?? originalMethod.call(this, window); - /* eslint-enable no-invalid-this */ - }, - ], - [ - Shell.WindowTracker.prototype, 'get_app_from_pid', - function (originalMethod, pid) { - /* eslint-disable no-invalid-this */ - const locationApp = Locations.getRunningApps().find(a => - a.get_pids().includes(pid)); - return locationApp ?? originalMethod.call(this, pid); - /* eslint-enable no-invalid-this */ - }, - ]); - - const {get: defaultFocusAppGetter} = Object.getOwnPropertyDescriptor( - Shell.WindowTracker.prototype, 'focus_app'); - this._propertyInjections.addWithLabel(Labels.LOCATIONS, - Shell.WindowTracker.prototype, 'focus_app', { - get() { - const locationApp = Locations.getRunningApps().find(a => a.isFocused); - return locationApp ?? defaultFocusAppGetter.call(this); - }, - }); - } - } - } - - _toggle() { - if (this._toggleLater) - return; - - this._toggleLater = Utils.laterAdd(Meta.LaterType.BEFORE_REDRAW, () => { - delete this._toggleLater; - this._restoreDash(); - this._deleteDocks(); - this._createDocks(); - this.emit('toggled'); - }); - } - - _mapExternalSetting(settings, key, mappedKey, mapValueFunction) { - const camelMappedKey = mappedKey.replace(/-([a-z\d])/g, k => k[1].toUpperCase()); - - const dockPropertyDesc = Object.getOwnPropertyDescriptor(this.settings, camelMappedKey); - - if (!dockPropertyDesc) - throw new Error('Setting %s not found in dock'.format(mappedKey)); - - const mappedValue = () => mapValueFunction(settings.get_value(key).recursiveUnpack()); - Object.defineProperty(this.settings, camelMappedKey, { - get: () => mappedValue() ?? dockPropertyDesc.value, - set: value => { - if (mappedValue()) - dockPropertyDesc.value = value; - }, - }); - - this._signalsHandler.addWithLabel(Labels.SETTINGS, settings, - 'changed::%s'.format(key), () => { - this._signalsHandler.blockWithLabel(Labels.SETTINGS); - this.settings.emit('changed::%s'.format(mappedKey), mappedKey); - this._signalsHandler.unblockWithLabel(Labels.SETTINGS); - }); - } - - _mapSettingsValues() { - this.settings.settingsSchema.list_keys().forEach(key => { - const camelKey = key.replace(/-([a-z\d])/g, k => k[1].toUpperCase()); - const updateSetting = () => { - const schemaKey = this.settings.settingsSchema.get_key(key); - if (schemaKey.get_range().deepUnpack()[0] === 'enum') - this.settings[camelKey] = this.settings.get_enum(key); - else - this.settings[camelKey] = this.settings.get_value(key).recursiveUnpack(); - }; - updateSetting(); - this._signalsHandler.addWithLabel(Labels.SETTINGS, this.settings, - `changed::${key}`, updateSetting); - if (key !== camelKey) { - Object.defineProperty(this.settings, key, - {get: () => this.settings[camelKey]}); - } - }); - Object.defineProperties(this.settings, { - dockExtended: {get: () => this.settings.extendHeight}, - }); - } - - _bindSettingsChanges() { - // Connect relevant signals to the toggling function - this._signalsHandler.addWithLabel(Labels.SETTINGS, [ - Utils.getMonitorManager(), - 'monitors-changed', - this._toggle.bind(this), - ], [ - Main.sessionMode, - 'updated', - this._toggle.bind(this), - ], [ - this._settings, - 'changed::multi-monitor', - this._toggle.bind(this), - ], [ - this._settings, - 'changed::preferred-monitor', - this._toggle.bind(this), - ], [ - this._settings, - 'changed::preferred-monitor-by-connector', - this._toggle.bind(this), - ], [ - this._settings, - 'changed::dock-position', - this._toggle.bind(this), - ], [ - this._settings, - 'changed::extend-height', - () => this._adjustPanelCorners(), - ], [ - this._settings, - 'changed::dock-fixed', - () => this._adjustPanelCorners(), - ], [ - this._settings, - 'changed::show-trash', - () => this._ensureLocations(), - ], [ - this._settings, - 'changed::show-mounts', - () => this._ensureLocations(), - ], [ - this._settings, - 'changed::isolate-locations', - () => this._ensureLocations(), - ], [ - this._settings, - 'changed::intellihide', - () => { - if (!this._settings.intellihide) - this._desktopIconsUsableArea.resetMargins(); - }, - ]); - - this._mapExternalSetting(this._appSwitcherSettings, 'current-workspace-only', - 'isolate-workspaces', value => value || undefined); - } - - _createDocks() { - // If there are no monitors (headless configurations, but it can also - // happen temporary while disconnecting and reconnecting monitors), just - // do nothing. When a monitor will be connected we we'll be notified and - // and thus create the docks. This prevents pointing trying to access - // monitors throughout the code, were we are assuming that at least the - // primary monitor is present. - if (Main.layoutManager.monitors.length <= 0) - return; - - - this._preferredMonitorIndex = this.settings.preferredMonitor; - if (this._preferredMonitorIndex === -2) { - const monitorManager = Utils.getMonitorManager(); - this._preferredMonitorIndex = monitorManager.get_monitor_for_connector( - this.settings.preferredMonitorByConnector); - } else if (this._preferredMonitorIndex >= 0) { - // Primary monitor used to be always 0 in Gdk, but the shell has a different - // concept (where the order depends on mutter order). - // So even if now the extension settings may use the same logic of the shell - // we prefer not to break the previously configured systems, and so we still - // assume that the gsettings monitor numbering follows the old strategy. - // This ensure the indexing in the settings and in the shell are matched, - // i.e. that we start counting from the primaryMonitorIndex - this._preferredMonitorIndex = - (Main.layoutManager.primaryIndex + this._preferredMonitorIndex) % - Main.layoutManager.monitors.length; - } - - // In case of multi-monitor, we consider the dock on the primary monitor - // to be the preferred (main) one regardless of the settings the dock - // goes on the primary monitor also if the settings are inconsistent - // (e.g. desired monitor not connected). - if (this.settings.multiMonitor || - this._preferredMonitorIndex < 0 || - this._preferredMonitorIndex > Main.layoutManager.monitors.length - 1) - this._preferredMonitorIndex = Main.layoutManager.primaryIndex; - - - // First we create the main Dock, to get the extra features to bind to this one - let dock = new DockedDash({ - monitorIndex: this._preferredMonitorIndex, - isMain: true, - }); - this._allDocks.push(dock); - - // connect app icon into the view selector - dock.dash.showAppsButton.connect('notify::checked', - this._onShowAppsButtonToggled.bind(this)); - - // Make the necessary changes to Main.overview.dash - this._prepareMainDash(); - - // Adjust corners if necessary - this._adjustPanelCorners(); - - if (this.settings.multiMonitor) { - const nMon = Main.layoutManager.monitors.length; - for (let iMon = 0; iMon < nMon; iMon++) { - if (iMon === this._preferredMonitorIndex) - continue; - dock = new DockedDash({monitorIndex: iMon}); - this._allDocks.push(dock); - // connect app icon into the view selector - dock.dash.showAppsButton.connect('notify::checked', - this._onShowAppsButtonToggled.bind(this)); - } - } - - // Load optional features. We load *after* the docks are created, since - // we need to connect the signals to all dock instances. - this._workspaceIsolation = new WorkspaceIsolation(); - this._keyboardShortcuts = new KeyboardShortcuts(); - - this.emit('docks-ready'); - } - - _prepareStartupAnimation() { - DockManager.allDocks.forEach(dock => { - const {dash} = dock; - - dock.opacity = 255; - dash.set({ - opacity: 0, - translation_x: 0, - translation_y: 0, - }); - }); - } - - _runStartupAnimation() { - DockManager.allDocks.forEach(dock => { - const {dash} = dock; - - switch (dock.position) { - case St.Side.LEFT: - dash.translation_x = -dash.width; - break; - case St.Side.RIGHT: - dash.translation_x = dash.width; - break; - case St.Side.BOTTOM: - dash.translation_y = dash.height; - break; - case St.Side.TOP: - dash.translation_y = -dash.height; - break; - } - - dash.ease({ - opacity: 255, - translation_x: 0, - translation_y: 0, - duration: STARTUP_ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - }); - } - - _prepareMainDash() { - // Ensure Main.overview.dash is set to our dash in dummy mode - // while just use the default getter otherwise. - // The getter must be dynamic and not set only when we've a dummy - // overview because the mode can change dynamically. - this._propertyInjections.removeWithLabel(Labels.MAIN_DASH); - const defaultDashGetter = Object.getOwnPropertyDescriptor( - Main.overview.constructor.prototype, 'dash').get; - this._propertyInjections.addWithLabel(Labels.MAIN_DASH, Main.overview, 'dash', { - get: () => Main.overview.isDummy - ? this.mainDock.dash : defaultDashGetter.call(Main.overview), - }); - - if (Main.overview.isDummy) - return; - - // Hide usual Dash - this._oldDash.hide(); - - // Also set dash width to 1, so it's almost not taken into account by code - // calculaing the reserved space in the overview. The reason to keep it at 1 is - // to allow its visibility change to trigger an allocaion of the appGrid which - // in turn is triggergin the appsIcon spring animation, required when no other - // actors has this effect, i.e in horizontal mode and without the workspaceThumnails - // 1 static workspace only) - this._oldDash.set_height(1); - - this._signalsHandler.addWithLabel(Labels.OLD_DASH_CHANGES, [ - this._oldDash, - 'notify::visible', - () => this._oldDash.hide(), - ], [ - this._oldDash, - 'notify::height', - () => this._oldDash.set_height(1), - ]); - - // Pretend I'm the dash: meant to make appgrid swarm animation come from - // the right position of the appShowButton. - this.overviewControls.dash = this.mainDock.dash; - this.searchController._showAppsButton = this.mainDock.dash.showAppsButton; - - // We also need to ignore max-size changes - this._methodInjections.addWithLabel(Labels.MAIN_DASH, this._oldDash, - 'setMaxSize', () => {}); - this._methodInjections.addWithLabel(Labels.MAIN_DASH, this._oldDash, - 'allocate', () => {}); - // And to return the preferred height depending on the state - this._methodInjections.addWithLabel(Labels.MAIN_DASH, this._oldDash, - 'get_preferred_height', (_originalMethod, ...args) => { - if (this.mainDock.isHorizontal && !this.settings.dockFixed) - return this.mainDock.get_preferred_height(...args); - return [0, 0]; - }); - - // FIXME: https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2890 - // const { ControlsManagerLayout } = OverviewControls; - const ControlsManagerLayout = this.overviewControls.layout_manager.constructor; - - const maybeAdjustBoxSize = (state, box, spacing) => { - // ensure that an undefined value will be converted into a valid one - spacing = spacing ?? 0; - - if (state === OverviewControls.ControlsState.WINDOW_PICKER) { - const searchBox = this.overviewControls._searchEntry.get_allocation_box(); - const {shouldShow: wsThumbnails} = this.overviewControls._thumbnailsBox; - - if (!wsThumbnails) { - box.y1 += spacing; - box.y2 -= spacing; - } - - box.y2 -= searchBox.get_height() + 2 * spacing; - } - - return box; - }; - - const maybeAdjustBoxToDock = (state, box, spacing) => { - maybeAdjustBoxSize(state, box, spacing); - - if (this.mainDock.isHorizontal || this.settings.dockFixed) - return box; - - const [, preferredWidth] = this.mainDock.get_preferred_width( - box.get_height()); - - if (this.mainDock.position === St.Side.LEFT) - box.x1 += preferredWidth; - else if (this.mainDock.position === St.Side.RIGHT) - box.x2 -= preferredWidth; - - return box; - }; - - this._vfuncInjections.addWithLabel(Labels.MAIN_DASH, ControlsManagerLayout.prototype, - 'allocate', function (container) { - /* eslint-disable no-invalid-this */ - const oldPostAllocation = this._runPostAllocation; - this._runPostAllocation = () => {}; - - const monitor = Main.layoutManager.findMonitorForActor(this._container); - const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index); - const startX = workArea.x - monitor.x; - const startY = workArea.y - monitor.y; - const workAreaBox = new Clutter.ActorBox(); - workAreaBox.set_origin(startX, startY); - workAreaBox.set_size(workArea.width, workArea.height); - - // GNOME 46 changes "spacing" to "_spacing". - const spacing = this.spacing ?? this._spacing; - - maybeAdjustBoxToDock(undefined, workAreaBox, spacing); - const oldStartY = workAreaBox.y1; - - const propertyInjections = new Utils.PropertyInjectionsHandler(); - propertyInjections.add(Main.layoutManager.panelBox, 'height', {value: startY}); - - if (Main.layoutManager.panelBox.y === Main.layoutManager.primaryMonitor.y) - workAreaBox.y1 -= oldStartY; - - this.vfunc_allocate(container, workAreaBox); - - propertyInjections.destroy(); - workAreaBox.y1 = oldStartY; - - const adjustActorHorizontalAllocation = actor => { - if (!actor.visible || !workAreaBox.x1) - return; - - const contentBox = actor.get_allocation_box(); - contentBox.set_size(workAreaBox.get_width(), contentBox.get_height()); - contentBox.set_origin(workAreaBox.x1, contentBox.y1); - actor.allocate(contentBox); - }; - - [this._searchEntry, this._workspacesThumbnails, this._searchController].forEach( - actor => adjustActorHorizontalAllocation(actor)); - - this._runPostAllocation = oldPostAllocation; - this._runPostAllocation(); - /* eslint-enable no-invalid-this */ - }); - - /** - * This can be removed or bypassed when GNOME/gnome-shell!1892 will be merged - * - * @param originalFunction - * @param state - * @param workAreaBox - * @param {...any} args - */ - function workspaceBoxOriginFixer(originalFunction, state, workAreaBox, ...args) { - /* eslint-disable no-invalid-this */ - const workspaceBox = originalFunction.call(this, state, workAreaBox, ...args); - workspaceBox.set_origin(workAreaBox.x1, workspaceBox.y1); - return workspaceBox; - /* eslint-enable no-invalid-this */ - } - - this._methodInjections.addWithLabel(Labels.MAIN_DASH, [ - ControlsManagerLayout.prototype, - '_computeWorkspacesBoxForState', - function (originalFunction, state, ...args) { - /* eslint-disable no-invalid-this */ - if (state === OverviewControls.ControlsState.HIDDEN) - return originalFunction.call(this, state, ...args); - - const box = workspaceBoxOriginFixer.call(this, originalFunction, state, ...args); - // GNOME 46 changes "spacing" to "_spacing". - const spacing = this.spacing ?? this._spacing; - const dock = DockManager.getDefault().getDockByMonitor(Main.layoutManager.primaryIndex); - if (!dock) - return box; - else - return maybeAdjustBoxSize(state, box, spacing); - /* eslint-enable no-invalid-this */ - }, - ], [ - WorkspacesView.SecondaryMonitorDisplay.prototype, - '_getWorkspacesBoxForState', - function (originalFunction, state, ...args) { - /* eslint-disable no-invalid-this */ - if (state === OverviewControls.ControlsState.HIDDEN) - return originalFunction.call(this, state, ...args); - - const box = workspaceBoxOriginFixer.call(this, originalFunction, state, ...args); - const dock = DockManager.getDefault().getDockByMonitor(this._monitorIndex); - if (!dock) - return box; - if (state === OverviewControls.ControlsState.WINDOW_PICKER && - dock.position === St.Side.BOTTOM) { - const [, preferredHeight] = dock.get_preferred_height(box.get_width()); - box.y2 -= preferredHeight; - } - return box; - /* eslint-enable no-invalid-this */ - }, - ], [ - ControlsManagerLayout.prototype, - '_getAppDisplayBoxForState', - function (originalFunction, ...args) { - /* eslint-disable no-invalid-this */ - return workspaceBoxOriginFixer.call(this, originalFunction, ...args); - /* eslint-enable no-invalid-this */ - }, - ]); - - this._vfuncInjections.addWithLabel(Labels.MAIN_DASH, Workspace.WorkspaceBackground.prototype, - 'allocate', function (box) { - /* eslint-disable no-invalid-this */ - this.vfunc_allocate(box); - - // This code has been submitted upstream via GNOME/gnome-shell!1892 - // so can be removed when that gets merged (or bypassed on newer shell - // versions). - const monitor = Main.layoutManager.monitors[this._monitorIndex]; - const [contentWidth, contentHeight] = this._bin.get_content_box().get_size(); - const [mX1, mX2] = [monitor.x, monitor.x + monitor.width]; - const [mY1, mY2] = [monitor.y, monitor.y + monitor.height]; - const [wX1, wX2] = [this._workarea.x, this._workarea.x + this._workarea.width]; - const [wY1, wY2] = [this._workarea.y, this._workarea.y + this._workarea.height]; - const xScale = contentWidth / this._workarea.width; - const yScale = contentHeight / this._workarea.height; - const leftOffset = wX1 - mX1; - const topOffset = wY1 - mY1; - const rightOffset = mX2 - wX2; - const bottomOffset = mY2 - wY2; - - const contentBox = new Clutter.ActorBox(); - contentBox.set_origin(-leftOffset * xScale, -topOffset * yScale); - contentBox.set_size( - contentWidth + (leftOffset + rightOffset) * xScale, - contentHeight + (topOffset + bottomOffset) * yScale); - - this._backgroundGroup.allocate(contentBox); - /* eslint-enable no-invalid-this */ - }); - - // Reduce the space that the workspaces can use in secondary monitors - this._methodInjections.addWithLabel(Labels.MAIN_DASH, WorkspacesView.WorkspacesView.prototype, - '_getFirstFitAllWorkspaceBox', function (originalFunction, ...args) { - /* eslint-disable no-invalid-this */ - const box = originalFunction.call(this, ...args); - if (DockManager.settings.dockFixed || - this._monitorIndex === Main.layoutManager.primaryIndex) - return box; - - const dock = DockManager.getDefault().getDockByMonitor(this._monitorIndex); - if (!dock) - return box; - - if (dock.isHorizontal) { - const [, preferredHeight] = dock.get_preferred_height(box.get_width()); - box.y2 -= preferredHeight; - if (dock.position === St.Side.TOP) - box.set_origin(box.x1, box.y1 + preferredHeight); - } else { - const [, preferredWidth] = dock.get_preferred_width(box.get_height()); - box.x2 -= preferredWidth / 2; - if (dock.position === St.Side.LEFT) - box.set_origin(box.x1 + preferredWidth, box.y1); - } - return box; - /* eslint-enable no-invalid-this */ - }); - - if (AppDisplay.BaseAppView?.prototype?._pageForCoords) { - // Ensure we handle Dnd events happening on the dock when we're - // dragging from AppDisplay. - // Remove when merged - // https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2002 - this._methodInjections.addWithLabel(Labels.MAIN_DASH, - AppDisplay.BaseAppView.prototype, - '_pageForCoords', function (originalFunction, ...args) { - /* eslint-disable no-invalid-this */ - if (!this._scrollView.has_pointer) - return AppDisplay.SidePages.NONE; - return originalFunction.call(this, ...args); - /* eslint-enable no-invalid-this */ - }); - } - - if (Main.layoutManager._startingUp) { - this._prepareStartupAnimation(); - - const hadOverview = Main.sessionMode.hasOverview; - - // Convince LayoutManager to use the legacy startup animation: - if (this._settings.disableOverviewOnStartup) - Main.sessionMode.hasOverview = false; - - this._signalsHandler.addWithLabel(Labels.STARTUP_ANIMATION, - Main.layoutManager, 'startup-complete', () => { - this._signalsHandler.removeWithLabel(Labels.STARTUP_ANIMATION); - Main.sessionMode.hasOverview = hadOverview; - this._runStartupAnimation(); - }); - } - } - - _deleteDocks() { - if (!this._allDocks.length) - return; - - // Remove extra features - this._workspaceIsolation.destroy(); - this._keyboardShortcuts.destroy(); - this._desktopIconsUsableArea.resetMargins(); - - // Delete all docks - this._allDocks.forEach(d => d.destroy()); - this._allDocks = []; - - this.emit('docks-destroyed'); - } - - _restoreDash() { - if (!this._oldDash) - return; - - this._signalsHandler.removeWithLabel(Labels.OLD_DASH_CHANGES); - [this._methodInjections, this._vfuncInjections, this._propertyInjections].forEach( - injections => injections.removeWithLabel(Labels.MAIN_DASH)); - - this.overviewControls.layout_manager._dash = this._oldDash; - this.overviewControls.dash = this._oldDash; - this.searchController._showAppsButton = this._oldDash.showAppsButton; - Main.overview.dash.show(); - Main.overview.dash.set_height(-1); // reset default dash size - // This force the recalculation of the icon size - Main.overview.dash._maxHeight = -1; - } - - get overviewControls() { - return Main.overview._overview.controls; - } - - get searchController() { - return this.overviewControls._searchController; - } - - _onShowAppsButtonToggled(button) { - const {checked} = button; - const {overviewControls} = this; - - if (!Main.overview.visible) { - this.mainDock.dash.showAppsButton._fromDesktop = true; - if (this._settings.animateShowApps) { - Main.overview.show(OverviewControls.ControlsState.APP_GRID); - } else { - GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - const oldAnimationTime = OverviewControls.SIDE_CONTROLS_ANIMATION_TIME; - Overview.ANIMATION_TIME = 1; - const id = Main.overview.connect('shown', () => { - Overview.ANIMATION_TIME = oldAnimationTime; - Main.overview.disconnect(id); - }); - Main.overview.show(OverviewControls.ControlsState.APP_GRID); - return GLib.SOURCE_REMOVE; - }); - } - } else if (!checked && this.mainDock.dash.showAppsButton._fromDesktop) { - if (this._settings.animateShowApps) { - Main.overview.hide(); - this.mainDock.dash.showAppsButton._fromDesktop = false; - } else { - GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - const oldAnimationTime = Overview.ANIMATION_TIME; - Overview.ANIMATION_TIME = 1; - const id = Main.overview.connect('hidden', () => { - Overview.ANIMATION_TIME = oldAnimationTime; - Main.overview.disconnect(id); - }); - Main.overview.hide(); - this.mainDock.dash.showAppsButton._fromDesktop = false; - return GLib.SOURCE_REMOVE; - }); - } - } else { - // TODO: I'm not sure how reliable this is, we might need to move the - // _onShowAppsButtonToggled logic into the extension. - if (!checked) - this.mainDock.dash.showAppsButton._fromDesktop = false; - - - // Instead of "syncing" the stock button, let's call its callback directly. - overviewControls._onShowAppsButtonToggled(); - } - - // Because we "disconnected" from the search controller, we have to manage its state. - this.searchController._setSearchActive(false); - } - - destroy() { - this.emit('destroy'); - if (this._toggleLater) { - Utils.laterRemove(this._toggleLater); - delete this._toggleLater; - } - this._restoreDash(); - this._deleteDocks(); - this._revertPanelCorners(); - if (this._oldSelectorMargin) - this.searchController.margin_bottom = this._oldSelectorMargin; - if (this._fm1Client) { - this._fm1Client.destroy(); - this._fm1Client = null; - } - this._notificationsMonitor.destroy(); - this._appSpread.destroy(); - this._trash?.destroy(); - this._trash = null; - Locations.unWrapFileManagerApp(); - this._removables?.destroy(); - this._removables = null; - this._iconTheme = null; - this._remoteModel?.destroy(); - this._settings = null; - this._appSwitcherSettings = null; - this._oldDash = null; - - this._desktopIconsUsableArea.destroy(); - this._desktopIconsUsableArea = null; - this._extension = null; - DockManager._singleton = null; - } - - /** - * Adjust Panel corners, remove this when 41 won't be supported anymore - */ - _adjustPanelCorners() { - if (!this._hasPanelCorners()) - return; - - const position = Utils.getPosition(); - const isHorizontal = (position === St.Side.TOP) || (position === St.Side.BOTTOM); - const dockOnPrimary = this._settings.multiMonitor || - this._preferredMonitorIndex === Main.layoutManager.primaryIndex; - - if (!isHorizontal && dockOnPrimary && this.settings.dockExtended && this.settings.dockFixed) { - Main.panel._rightCorner.hide(); - Main.panel._leftCorner.hide(); - } else { - this._revertPanelCorners(); - } - } - - _revertPanelCorners() { - if (!this._hasPanelCorners()) - return; - - Main.panel._leftCorner.show(); - Main.panel._rightCorner.show(); - } - - _hasPanelCorners() { - return !!Main.panel?._rightCorner && !!Main.panel?._leftCorner; - } -} -Signals.addSignalMethods(DockManager.prototype); - -// This class drives long-running icon animations, to keep them running in sync -// with each other, and to save CPU by pausing them when the dock is hidden. -export class IconAnimator { - constructor(actor) { - this._count = 0; - this._started = false; - this._animations = { - wiggle: [], - }; - this._timeline = new Clutter.Timeline({ - duration: AnimationUtils.adjustAnimationTime(ICON_ANIMATOR_DURATION) || 1, - repeat_count: -1, - actor, - }); - - this._updateSettings(); - this._settingsChangedId = St.Settings.get().connect('notify', - () => this._updateSettings()); - - this._timeline.connect('new-frame', () => { - const progress = this._timeline.get_progress(); - const wiggleRotation = progress < 1 / 6 ? 15 * Math.sin(progress * 24 * Math.PI) : 0; - const wigglers = this._animations.wiggle; - for (let i = 0, iMax = wigglers.length; i < iMax; i++) - wigglers[i].target.rotation_angle_z = wiggleRotation; - }); - } - - _updateSettings() { - this._timeline.set_duration( - AnimationUtils.adjustAnimationTime(ICON_ANIMATOR_DURATION) || 1); - } - - destroy() { - St.Settings.get().disconnect(this._settingsChangedId); - this._timeline.stop(); - this._timeline = null; - for (const pairs of Object.values(this._animations)) { - for (let i = 0, iMax = pairs.length; i < iMax; i++) { - const pair = pairs[i]; - pair.target.disconnect(pair.targetDestroyId); - } - } - this._animations = null; - } - - pause() { - if (this._started && this._count > 0) - this._timeline.stop(); - - this._started = false; - } - - start() { - if (!this._started && this._count > 0) - this._timeline.start(); - - this._started = true; - } - - addAnimation(target, name) { - const targetDestroyId = target.connect('destroy', - () => this.removeAnimation(target, name)); - this._animations[name].push({target, targetDestroyId}); - if (this._started && this._count === 0) - this._timeline.start(); - - this._count++; - } - - removeAnimation(target, name) { - const pairs = this._animations[name]; - for (let i = 0, iMax = pairs.length; i < iMax; i++) { - const pair = pairs[i]; - if (pair.target === target) { - target.disconnect(pair.targetDestroyId); - pairs.splice(i, 1); - this._count--; - if (this._started && this._count === 0) - this._timeline.stop(); - - return; - } - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/extension.js deleted file mode 100755 index 68de2acb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/extension.js +++ /dev/null @@ -1,18 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import {DockManager} from './docking.js'; -import {Extension} from './dependencies/shell/extensions/extension.js'; - -// We export this so it can be accessed by other extensions -export let dockManager; - -export default class DashToDockExtension extends Extension.Extension { - enable() { - dockManager = new DockManager(this); - } - - disable() { - dockManager?.destroy(); - dockManager = null; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/fileManager1API.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/fileManager1API.js deleted file mode 100755 index 192214a9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/fileManager1API.js +++ /dev/null @@ -1,201 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import {GLib, Gio} from './dependencies/gi.js'; -const {signals: Signals} = imports; - -import {Utils} from './imports.js'; - -const FileManager1Iface = '\ - \ - '; - -const FileManager1Proxy = Gio.DBusProxy.makeProxyWrapper(FileManager1Iface); - -const Labels = Object.freeze({ - WINDOWS: Symbol('windows'), -}); - -/** - * This class implements a client for the org.freedesktop.FileManager1 dbus - * interface, and specifically for the OpenWindowsWithLocations property - * which is published by Nautilus, but is not an official part of the interface. - * - * The property is a map from window identifiers to a list of locations open in - * the window. - */ -export class FileManager1Client { - constructor() { - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._cancellable = new Gio.Cancellable(); - - this._windowsByPath = new Map(); - this._windowsByLocation = new Map(); - this._proxy = new FileManager1Proxy(Gio.DBus.session, - 'org.freedesktop.FileManager1', - '/org/freedesktop/FileManager1', - (initable, error) => { - // Use async construction to avoid blocking on errors. - if (error) { - if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - global.log(error); - } else { - this._updateWindows(); - this._updateLocationMap(); - } - }, this._cancellable); - - this._signalsHandler.add([ - this._proxy, - 'g-properties-changed', - this._onPropertyChanged.bind(this), - ], [ - // We must additionally listen for Screen events to know when to - // rebuild our location map when the set of available windows changes. - global.workspaceManager, - 'workspace-added', - () => this._onWindowsChanged(), - ], [ - global.workspaceManager, - 'workspace-removed', - () => this._onWindowsChanged(), - ], [ - global.display, - 'window-entered-monitor', - () => this._onWindowsChanged(), - ], [ - global.display, - 'window-left-monitor', - () => this._onWindowsChanged(), - ]); - } - - destroy() { - if (this._windowsUpdateIdle) { - GLib.source_remove(this._windowsUpdateIdle); - delete this._windowsUpdateIdle; - } - this._cancellable.cancel(); - this._signalsHandler.destroy(); - this._windowsByLocation.clear(); - this._windowsByPath.clear(); - this._proxy = null; - } - - /** - * Return an array of windows that are showing a location or - * sub-directories of that location. - * - * @param location - */ - getWindows(location) { - if (!location) - return []; - - location += location.endsWith('/') ? '' : '/'; - const windows = []; - this._windowsByLocation.forEach((wins, l) => { - if (l.startsWith(location)) - windows.push(...wins); - }); - return [...new Set(windows)]; - } - - _onPropertyChanged(proxy, changed, _invalidated) { - const property = changed.unpack(); - if (property && - ('OpenWindowsWithLocations' in property)) - this._updateLocationMap(); - } - - _updateWindows() { - const oldSize = this._windowsByPath.size; - const oldPaths = this._windowsByPath.keys(); - this._windowsByPath = Utils.getWindowsByObjectPath(); - - if (oldSize !== this._windowsByPath.size) - return true; - - return [...oldPaths].some(path => !this._windowsByPath.has(path)); - } - - _onWindowsChanged() { - if (this._windowsUpdateIdle) - return; - - this._windowsUpdateIdle = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - if (this._updateWindows()) - this._updateLocationMap(); - - delete this._windowsUpdateIdle; - return GLib.SOURCE_REMOVE; - }); - } - - _updateLocationMap() { - const properties = this._proxy.get_cached_property_names(); - if (!properties) { - // Nothing to check yet. - return; - } - - if (properties.includes('OpenWindowsWithLocations')) - this._updateFromPaths(); - } - - _locationMapsEquals(mapA, mapB) { - if (mapA.size !== mapB.size) - return false; - - const setsEquals = (a, b) => a.size === b.size && - [...a].every(value => b.has(value)); - - for (const [key, val] of mapA) { - const windowsSet = mapB.get(key); - if (!windowsSet || !setsEquals(windowsSet, val)) - return false; - } - return true; - } - - _updateFromPaths() { - const locationsByWindowsPath = this._proxy.OpenWindowsWithLocations; - - const windowsByLocation = new Map(); - this._signalsHandler.removeWithLabel(Labels.WINDOWS); - - Object.entries(locationsByWindowsPath).forEach(([windowPath, locations]) => { - locations.forEach(location => { - const win = this._windowsByPath.get(windowPath); - const windowGroup = win ? [win] : []; - - win?.foreach_transient(w => windowGroup.push(w) || true); - - windowGroup.forEach(window => { - location += location.endsWith('/') ? '' : '/'; - // Use a set to deduplicate when a window has a - // location open in multiple tabs. - const windows = windowsByLocation.get(location) || new Set(); - windows.add(window); - - if (windows.size === 1) - windowsByLocation.set(location, windows); - - this._signalsHandler.addWithLabel(Labels.WINDOWS, window, - 'unmanaged', () => { - const wins = this._windowsByLocation.get(location); - wins.delete(window); - if (!wins.size) - this._windowsByLocation.delete(location); - this.emit('windows-changed'); - }); - }); - }); - }); - - if (!this._locationMapsEquals(this._windowsByLocation, windowsByLocation)) { - this._windowsByLocation = windowsByLocation; - this.emit('windows-changed'); - } - } -} -Signals.addSignalMethods(FileManager1Client.prototype); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/imports.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/imports.js deleted file mode 100755 index 7921d4b1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/imports.js +++ /dev/null @@ -1,16 +0,0 @@ -export * as AppIconIndicators from './appIconIndicators.js'; -export * as AppIcons from './appIcons.js'; -export * as AppSpread from './appSpread.js'; -export * as DockDash from './dash.js'; -export * as DBusMenuUtils from './dbusmenuUtils.js'; -export * as DesktopIconsIntegration from './desktopIconsIntegration.js'; -export * as Docking from './docking.js'; -export * as Extension from './extension.js'; -export * as FileManager1API from './fileManager1API.js'; -export * as Intellihide from './intellihide.js'; -export * as LauncherAPI from './launcherAPI.js'; -export * as Locations from './locations.js'; -export * as NotificationsMonitor from './notificationsMonitor.js'; -export * as Theming from './theming.js'; -export * as Utils from './utils.js'; -export * as WindowPreview from './windowPreview.js'; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/intellihide.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/intellihide.js deleted file mode 100755 index 9cab2a66..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/intellihide.js +++ /dev/null @@ -1,337 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - GLib, - Meta, - Shell, -} from './dependencies/gi.js'; - -import { - Docking, - Utils, -} from './imports.js'; - -const {signals: Signals} = imports; - -// A good compromise between reactivity and efficiency; to be tuned. -const INTELLIHIDE_CHECK_INTERVAL = 100; - -const OverlapStatus = Object.freeze({ - UNDEFINED: -1, - FALSE: 0, - TRUE: 1, -}); - -const IntellihideMode = Object.freeze({ - ALL_WINDOWS: 0, - FOCUS_APPLICATION_WINDOWS: 1, - MAXIMIZED_WINDOWS: 2, - ALWAYS_ON_TOP: 3, -}); - -// List of windows type taken into account. Order is important (keep the original -// enum order). -const handledWindowTypes = [ - Meta.WindowType.NORMAL, - Meta.WindowType.DOCK, - Meta.WindowType.DIALOG, - Meta.WindowType.MODAL_DIALOG, - Meta.WindowType.TOOLBAR, - Meta.WindowType.MENU, - Meta.WindowType.UTILITY, - Meta.WindowType.SPLASHSCREEN, - Meta.WindowType.DROPDOWN_MENU, -]; - -// List of applications, ignore windows of these applications in considering intellihide -const ignoreApps = ['com.rastersoft.ding', 'com.desktop.ding']; - -/** - * A rough and ugly implementation of the intellihide behaviour. - * Intallihide object: emit 'status-changed' signal when the overlap of windows - * with the provided targetBoxClutter.ActorBox changes; - */ -export class Intellihide { - constructor(monitorIndex) { - // Load settings - this._monitorIndex = monitorIndex; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._tracker = Shell.WindowTracker.get_default(); - this._focusApp = null; // The application whose window is focused. - this._topApp = null; // The application whose window is on top on the monitor with the dock. - - this._isEnabled = false; - this.status = OverlapStatus.UNDEFINED; - this._targetBox = null; - - this._checkOverlapTimeoutContinue = false; - this._checkOverlapTimeoutId = 0; - - this._trackedWindows = new Map(); - - // Connect global signals - this._signalsHandler.add([ - // Add signals on windows created from now on - global.display, - 'window-created', - this._windowCreated.bind(this), - ], [ - // triggered for instance when the window list order changes, - // included when the workspace is switched - global.display, - 'restacked', - this._checkOverlap.bind(this), - ], [ - // when windows are alwasy on top, the focus window can change - // without the windows being restacked. Thus monitor window focus change. - this._tracker, - 'notify::focus-app', - this._checkOverlap.bind(this), - ], [ - // update wne monitor changes, for instance in multimonitor when monitor are attached - Utils.getMonitorManager(), - 'monitors-changed', - this._checkOverlap.bind(this), - ]); - } - - destroy() { - // Disconnect global signals - this._signalsHandler.destroy(); - - // Remove residual windows signals - this.disable(); - } - - enable() { - this._isEnabled = true; - this._status = OverlapStatus.UNDEFINED; - global.get_window_actors().forEach(function (wa) { - this._addWindowSignals(wa); - }, this); - this._doCheckOverlap(); - } - - disable() { - this._isEnabled = false; - - for (const wa of this._trackedWindows.keys()) - this._removeWindowSignals(wa); - - this._trackedWindows.clear(); - - if (this._checkOverlapTimeoutId > 0) { - GLib.source_remove(this._checkOverlapTimeoutId); - this._checkOverlapTimeoutId = 0; - } - } - - _windowCreated(display, metaWindow) { - this._addWindowSignals(metaWindow.get_compositor_private()); - this._doCheckOverlap(); - } - - _addWindowSignals(wa) { - if (!this._handledWindow(wa)) - return; - const signalId = wa.connect('notify::allocation', this._checkOverlap.bind(this)); - this._trackedWindows.set(wa, signalId); - wa.connect('destroy', this._removeWindowSignals.bind(this)); - } - - _removeWindowSignals(wa) { - if (this._trackedWindows.get(wa)) { - wa.disconnect(this._trackedWindows.get(wa)); - this._trackedWindows.delete(wa); - } - } - - updateTargetBox(box) { - this._targetBox = box; - this._checkOverlap(); - } - - forceUpdate() { - this._status = OverlapStatus.UNDEFINED; - this._doCheckOverlap(); - } - - getOverlapStatus() { - return this._status === OverlapStatus.TRUE; - } - - _checkOverlap() { - if (!this._isEnabled || !this._targetBox) - return; - - /* Limit the number of calls to the doCheckOverlap function */ - if (this._checkOverlapTimeoutId) { - this._checkOverlapTimeoutContinue = true; - return; - } - - this._doCheckOverlap(); - - this._checkOverlapTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, INTELLIHIDE_CHECK_INTERVAL, () => { - this._doCheckOverlap(); - if (this._checkOverlapTimeoutContinue) { - this._checkOverlapTimeoutContinue = false; - return GLib.SOURCE_CONTINUE; - } else { - this._checkOverlapTimeoutId = 0; - return GLib.SOURCE_REMOVE; - } - }); - } - - _doCheckOverlap() { - if (!this._isEnabled || !this._targetBox) - return; - - let overlaps = OverlapStatus.FALSE; - let windows = global.get_window_actors().filter(wa => this._handledWindow(wa)); - - if (windows.length > 0) { - /* - * Get the top window on the monitor where the dock is placed. - * The idea is that we dont want to overlap with the windows of the topmost application, - * event is it's not the focused app -- for instance because in multimonitor the user - * select a window in the secondary monitor. - */ - - let topWindow = null; - for (let i = windows.length - 1; i >= 0; i--) { - const metaWin = windows[i].get_meta_window(); - if (metaWin.get_monitor() === this._monitorIndex) { - topWindow = metaWin; - break; - } - } - - if (topWindow) { - this._topApp = this._tracker.get_window_app(topWindow); - // If there isn't a focused app, use that of the window on top - this._focusApp = this._tracker.focus_app || this._topApp; - - windows = windows.filter(this._intellihideFilterInteresting, this); - - for (let i = 0; i < windows.length; i++) { - const win = windows[i].get_meta_window(); - - if (win) { - const rect = win.get_frame_rect(); - - const test = (rect.x < this._targetBox.x2) && - (rect.x + rect.width > this._targetBox.x1) && - (rect.y < this._targetBox.y2) && - (rect.y + rect.height > this._targetBox.y1); - - if (test) { - overlaps = OverlapStatus.TRUE; - break; - } - } - } - } - } - - if (this._status !== overlaps) { - this._status = overlaps; - this.emit('status-changed', this._status); - } - } - - // Filter interesting windows to be considered for intellihide. - // Consider all windows visible on the current workspace. - // Optionally skip windows of other applications - _intellihideFilterInteresting(wa) { - const metaWin = wa.get_meta_window(); - const currentWorkspace = global.workspace_manager.get_active_workspace_index(); - const workspace = metaWin.get_workspace(); - const workspaceIndex = workspace.index(); - - // Depending on the intellihide mode, exclude non-relevent windows - switch (Docking.DockManager.settings.intellihideMode) { - case IntellihideMode.ALL_WINDOWS: - // Do nothing - break; - - case IntellihideMode.FOCUS_APPLICATION_WINDOWS: - // Skip windows of other apps - if (this._focusApp) { - // The DropDownTerminal extension is not an application per se - // so we match its window by wm class instead - if (metaWin.get_wm_class() === 'DropDownTerminalWindow') - return true; - - const currentApp = this._tracker.get_window_app(metaWin); - const focusWindow = global.display.get_focus_window(); - - // Consider half maximized windows side by side - // and windows which are alwayson top - if (currentApp !== this._focusApp && currentApp !== this._topApp && - !((focusWindow && focusWindow.maximized_vertically && - !focusWindow.maximized_horizontally) && - (metaWin.maximized_vertically && !metaWin.maximized_horizontally) && - metaWin.get_monitor() === focusWindow.get_monitor()) && - !metaWin.is_above()) - return false; - } - break; - - case IntellihideMode.MAXIMIZED_WINDOWS: - // Skip unmaximized windows - if (!metaWin.maximized_vertically && !metaWin.maximized_horizontally && !metaWin.fullscreen) - return false; - break; - - case IntellihideMode.ALWAYS_ON_TOP: - // Always on top, except for fullscreen windows - if (this._focusApp) { - const {focusWindow} = global.display; - if (!focusWindow?.fullscreen) - return false; - } - break; - } - - if (workspaceIndex === currentWorkspace && metaWin.showing_on_its_workspace()) - return true; - else - return false; - } - - // Filter windows by type - // inspired by Opacify@gnome-shell.localdomain.pl - _handledWindow(wa) { - const metaWindow = wa.get_meta_window(); - - if (!metaWindow) - return false; - - // The DING extension desktop window needs to be excluded - // so we match its window by application id and window property. - const wmApp = metaWindow.get_gtk_application_id(); - if (ignoreApps.includes(wmApp) && metaWindow.is_skip_taskbar()) - return false; - - // The DropDownTerminal extension uses the POPUP_MENU window type hint - // so we match its window by wm class instead - if (metaWindow.get_wm_class() === 'DropDownTerminalWindow') - return true; - - const wtype = metaWindow.get_window_type(); - for (let i = 0; i < handledWindowTypes.length; i++) { - const hwtype = handledWindowTypes[i]; - if (hwtype === wtype) - return true; - else if (hwtype > wtype) - return false; - } - return false; - } -} - -Signals.addSignalMethods(Intellihide.prototype); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/launcherAPI.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/launcherAPI.js deleted file mode 100755 index cf08c38a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/launcherAPI.js +++ /dev/null @@ -1,286 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import {Gio} from './dependencies/gi.js'; -import {DBusMenuUtils} from './imports.js'; - -const DBusMenu = await DBusMenuUtils.haveDBusMenu(); - -export class LauncherEntryRemoteModel { - constructor() { - this._entrySourceStacks = new Map(); - this._remoteMaps = new Map(); - - this._launcher_entry_dbus_signal_id = - Gio.DBus.session.signal_subscribe(null, // sender - 'com.canonical.Unity.LauncherEntry', // iface - 'Update', // member - null, // path - null, // arg0 - Gio.DBusSignalFlags.NONE, - (_connection, senderName, _objectPath, _interfaceName, _signalName, parameters) => - this._onUpdate(senderName, ...parameters.deep_unpack())); - - this._dbus_name_owner_changed_signal_id = - Gio.DBus.session.signal_subscribe('org.freedesktop.DBus', // sender - 'org.freedesktop.DBus', // interface - 'NameOwnerChanged', // member - '/org/freedesktop/DBus', // path - null, // arg0 - Gio.DBusSignalFlags.NONE, - (connection, _senderName, _objectPath, _interfaceName, _signalName, parameters) => - this._onDBusNameChange(...parameters.deep_unpack().slice(1))); - - this._acquireUnityDBus(); - } - - destroy() { - if (this._launcher_entry_dbus_signal_id) - Gio.DBus.session.signal_unsubscribe(this._launcher_entry_dbus_signal_id); - - - if (this._dbus_name_owner_changed_signal_id) - Gio.DBus.session.signal_unsubscribe(this._dbus_name_owner_changed_signal_id); - - - this._releaseUnityDBus(); - } - - _lookupStackById(appId) { - let sourceStack = this._entrySourceStacks.get(appId); - if (!sourceStack) { - sourceStack = new PropertySourceStack(new LauncherEntry(), - launcherEntryDefaults); - this._entrySourceStacks.set(appId, sourceStack); - } - - return sourceStack; - } - - lookupById(appId) { - return this._lookupStackById(appId).target; - } - - _acquireUnityDBus() { - if (!this._unity_bus_id) { - this._unity_bus_id = Gio.DBus.session.own_name('com.canonical.Unity', - Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT | Gio.BusNameOwnerFlags.REPLACE, - null, () => (this._unity_bus_id = 0)); - } - } - - _releaseUnityDBus() { - if (this._unity_bus_id) { - Gio.DBus.session.unown_name(this._unity_bus_id); - this._unity_bus_id = 0; - } - } - - _onDBusNameChange(before, after) { - if (!before || !this._remoteMaps.size) - return; - - const remoteMap = this._remoteMaps.get(before); - if (!remoteMap) - return; - - this._remoteMaps.delete(before); - if (after && !this._remoteMaps.has(after)) { - this._remoteMaps.set(after, remoteMap); - } else { - for (const [appId, remote] of remoteMap) { - const sourceStack = this._entrySourceStacks.get(appId); - const changed = sourceStack.remove(remote); - if (changed) - sourceStack.target._emitChangedEvents(changed); - } - } - } - - _onUpdate(senderName, appUri, properties) { - if (!senderName) - return; - - - const appId = appUri.replace(/(^\w+:|^)\/\//, ''); - if (!appId) - return; - - - let remoteMap = this._remoteMaps.get(senderName); - if (!remoteMap) - this._remoteMaps.set(senderName, remoteMap = new Map()); - - let remote = remoteMap.get(appId); - if (!remote) - remoteMap.set(appId, remote = Object.assign({}, launcherEntryDefaults)); - - for (const name in properties) { - if (name === 'quicklist' && DBusMenu) { - const quicklistPath = properties[name].unpack(); - if (quicklistPath && - (!remote._quicklistMenuClient || - remote._quicklistMenuClient.dbus_object !== quicklistPath)) { - remote.quicklist = null; - let menuClient = remote._quicklistMenuClient; - if (menuClient) { - menuClient.dbus_object = quicklistPath; - } else { - // This property should not be enumerable - Object.defineProperty(remote, '_quicklistMenuClient', { - writable: true, - value: menuClient = new DBusMenu.Client({ - dbus_name: senderName, - dbus_object: quicklistPath, - }), - }); - } - const handler = () => { - const root = menuClient.get_root(); - if (remote.quicklist !== root) { - remote.quicklist = root; - if (sourceStack.isTop(remote)) { - sourceStack.target.quicklist = root; - sourceStack.target._emitChangedEvents(['quicklist']); - } - } - }; - menuClient.connect(DBusMenu.CLIENT_SIGNAL_ROOT_CHANGED, handler); - } - } else { - remote[name] = properties[name].unpack(); - } - } - - const sourceStack = this._lookupStackById(appId); - sourceStack.target._emitChangedEvents(sourceStack.update(remote)); - } -} - -const launcherEntryDefaults = Object.freeze({ - count: 0, - progress: 0, - urgent: false, - quicklist: null, - 'count-visible': false, - 'progress-visible': false, -}); - -const LauncherEntry = class DashToDockLauncherEntry { - constructor() { - this._connections = new Map(); - this._handlers = new Map(); - this._nextId = 0; - } - - connect(eventNames, callback) { - if (typeof eventNames === 'string') - eventNames = [eventNames]; - - callback(this, this); - const id = this._nextId++; - const handler = {id, callback}; - eventNames.forEach(name => { - let handlerList = this._handlers.get(name); - if (!handlerList) - this._handlers.set(name, handlerList = []); - - handlerList.push(handler); - }); - this._connections.set(id, eventNames); - return id; - } - - disconnect(id) { - const eventNames = this._connections.get(id); - if (!eventNames) - return; - - this._connections.delete(id); - eventNames.forEach(name => { - const handlerList = this._handlers.get(name); - if (handlerList) { - for (let i = 0, iMax = handlerList.length; i < iMax; i++) { - if (handlerList[i].id === id) { - handlerList.splice(i, 1); - break; - } - } - } - }); - } - - _emitChangedEvents(propertyNames) { - const handlers = new Set(); - propertyNames.forEach(name => { - const handlerList = this._handlers.get(`${name}-changed`); - if (handlerList) { - for (let i = 0, iMax = handlerList.length; i < iMax; i++) - handlers.add(handlerList[i]); - } - }); - Array.from(handlers).sort((x, y) => x.id - y.id).forEach(handler => handler.callback(this, this)); - } -}; - -for (const [name, defaultValue] of Object.entries(launcherEntryDefaults)) { - const jsName = name.replace(/-/g, '_'); - LauncherEntry.prototype[jsName] = defaultValue; - if (jsName !== name) { - Object.defineProperty(LauncherEntry.prototype, name, { - get() { - return this[jsName]; - }, - set(value) { - this[jsName] = value; - }, - }); - } -} - -const PropertySourceStack = class DashToDockPropertySourceStack { - constructor(target, bottom) { - this.target = target; - this._bottom = bottom; - this._stack = []; - } - - isTop(source) { - return this._stack.length > 0 && this._stack[this._stack.length - 1] === source; - } - - update(source) { - if (!this.isTop(source)) { - this.remove(source); - this._stack.push(source); - } - return this._assignFrom(source); - } - - remove(source) { - const stack = this._stack; - const top = stack[stack.length - 1]; - if (top === source) { - stack.length--; - return this._assignFrom(stack.length > 0 ? stack[stack.length - 1] : this._bottom); - } - for (let i = 0, iMax = stack.length; i < iMax; i++) { - if (stack[i] === source) { - stack.splice(i, 1); - break; - } - } - - return null; - } - - _assignFrom(source) { - const changedProperties = []; - for (const name in source) { - if (this.target[name] !== source[name]) { - this.target[name] = source[name]; - changedProperties.push(name); - } - } - return changedProperties; - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ar/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ar/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 75fbaacf..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ar/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/cs/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/cs/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 7b092bfb..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/cs/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/de/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/de/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index b3bf5f5d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/de/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/el/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/el/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index c64aa832..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/el/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/es/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/es/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 63c0c16b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/es/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/eu/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/eu/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 044406f8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/eu/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/fr/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/fr/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 2a0c8381..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/fr/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/gl/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/gl/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 110db825..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/gl/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/hu/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/hu/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 49cf08bb..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/hu/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/id/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/id/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 3ea32d5c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/id/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/it/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/it/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 56361a5c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/it/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ja/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ja/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index a2ba4ef8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ja/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ko/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ko/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index a0c1f46f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ko/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/nb/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/nb/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index db5ad46a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/nb/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/nl/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/nl/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index e926ee03..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/nl/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pl/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pl/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index a48230d5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pl/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pt/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pt/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 9733e407..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pt/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pt_BR/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pt_BR/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 2d7aecd6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/pt_BR/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ru/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ru/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 25b5db90..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/ru/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sk/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sk/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 9348b7e2..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sk/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sl/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sl/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index aea0c421..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sl/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sr/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sr/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index b5e6fb6b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sr/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sr@latin/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sr@latin/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 8dfc69e5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sr@latin/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sv/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sv/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index ebedb034..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/sv/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/tr/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/tr/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 1ba9027f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/tr/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/uk_UA/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/uk_UA/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index 9ce6eaac..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/uk_UA/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/zh_CN/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/zh_CN/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index f740ba23..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/zh_CN/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/zh_TW/LC_MESSAGES/dashtodock.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/zh_TW/LC_MESSAGES/dashtodock.mo deleted file mode 100755 index bdb05ad9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locale/zh_TW/LC_MESSAGES/dashtodock.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locations.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locations.js deleted file mode 100755 index bf20de80..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locations.js +++ /dev/null @@ -1,1471 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Gio, - GLib, - GObject, - Shell, - St, -} from './dependencies/gi.js'; - -import {ShellMountOperation} from './dependencies/shell/ui.js'; - -import { - Docking, - Utils, -} from './imports.js'; - -import {Extension} from './dependencies/shell/extensions/extension.js'; - -// Use __ () and N__() for the extension gettext domain, and reuse -// the shell domain with the default _() and N_() -const {gettext: __} = Extension; - -const {signals: Signals} = imports; - -const FALLBACK_REMOVABLE_MEDIA_ICON = 'drive-removable-media'; -const FALLBACK_TRASH_ICON = 'user-trash'; -const FILE_MANAGER_DESKTOP_APP_ID = 'org.gnome.Nautilus.desktop'; -const ATTRIBUTE_METADATA_CUSTOM_ICON = 'metadata::custom-icon'; -const TRASH_URI = 'trash://'; -const UPDATE_TRASH_DELAY = 1000; -const LAUNCH_HANDLER_MAX_WAIT = 200; - -const NautilusFileOperations2Interface = '\ - \ - \ - \ - \ - \ - \ -'; - -const NautilusFileOperations2ProxyInterface = - Gio.DBusProxy.makeProxyWrapper(NautilusFileOperations2Interface); - -const Labels = Object.freeze({ - LOCATION_WINDOWS: Symbol('location-windows'), - WINDOWS_CHANGED: Symbol('windows-changed'), -}); - -const GJS_SUPPORTS_FILE_IFACE_PROMISES = imports.system.version >= 17101; - -if (GJS_SUPPORTS_FILE_IFACE_PROMISES) { - Gio._promisify(Gio.File.prototype, 'query_info_async'); - Gio._promisify(Gio.File.prototype, 'query_default_handler_async'); -} - - -/** - * - */ -function makeNautilusFileOperationsProxy() { - const proxy = new NautilusFileOperations2ProxyInterface( - Gio.DBus.session, - 'org.gnome.Nautilus', - '/org/gnome/Nautilus/FileOperations2', (_p, error) => { - if (error) - logError(error, 'Error connecting to Nautilus'); - } - ); - - proxy.platformData = params => { - const defaultParams = { - parentHandle: '', - timestamp: global.get_current_time(), - windowPosition: 'center', - }; - const {parentHandle, timestamp, windowPosition} = { - ...defaultParams, - ...params, - }; - - return { - 'parent-handle': new GLib.Variant('s', parentHandle), - 'timestamp': new GLib.Variant('u', timestamp), - 'window-position': new GLib.Variant('s', windowPosition), - }; - }; - - return proxy; -} - -export const LocationAppInfo = GObject.registerClass({ - Implements: [Gio.AppInfo], - Properties: { - 'location': GObject.ParamSpec.object( - 'location', 'location', 'location', - GObject.ParamFlags.READWRITE, - Gio.File.$gtype), - 'name': GObject.ParamSpec.string( - 'name', 'name', 'name', - GObject.ParamFlags.READWRITE, - null), - 'icon': GObject.ParamSpec.object( - 'icon', 'icon', 'icon', - GObject.ParamFlags.READWRITE, - Gio.Icon.$gtype), - 'cancellable': GObject.ParamSpec.object( - 'cancellable', 'cancellable', 'cancellable', - GObject.ParamFlags.READWRITE, - Gio.Cancellable.$gtype), - }, -}, class LocationAppInfo extends Gio.DesktopAppInfo { - static get GJS_BINARY_PATH() { - if (!this._gjsBinaryPath) - this._gjsBinaryPath = GLib.find_program_in_path('gjs'); - - return this._gjsBinaryPath; - } - - list_actions() { - return []; - } - - get_action_name() { - return null; - } - - get_boolean() { - return false; - } - - vfunc_dup() { - return new LocationAppInfo({ - location: this.location, - name: this.name, - icon: this.icon, - cancellable: this.cancellable, - }); - } - - vfunc_equal(other) { - if (this.location) - return this.location.equal(other?.location); - - return this.name === other.name && - (this.icon ? this.icon.equal(other?.icon) : !other?.icon); - } - - vfunc_get_id() { - return 'location:%s'.format(this.location?.get_uri()); - } - - vfunc_get_name() { - return this.name; - } - - vfunc_get_description() { - return null; - } - - vfunc_get_executable() { - return null; - } - - vfunc_get_icon() { - return this.icon; - } - - vfunc_launch(files, context) { - if (files?.length) { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_SUPPORTED, 'Launching with files not supported'); - } - - return this.getHandlerApp().launch_uris([this.location.get_uri()], context); - } - - vfunc_supports_uris() { - return false; - } - - vfunc_supports_files() { - return false; - } - - vfunc_launch_uris(uris, context) { - return this.launch(uris, context); - } - - vfunc_should_show() { - return true; - } - - vfunc_set_as_default_for_type() { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_SUPPORTED, 'Not supported'); - } - - vfunc_set_as_default_for_extension() { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_SUPPORTED, 'Not supported'); - } - - vfunc_add_supports_type() { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_SUPPORTED, 'Not supported'); - } - - vfunc_can_remove_supports_type() { - return false; - } - - vfunc_remove_supports_type() { - return false; - } - - vfunc_can_delete() { - return false; - } - - vfunc_do_delete() { - return false; - } - - vfunc_get_commandline() { - try { - return this.getHandlerApp().get_commandline(); - } catch { - return this._getFallbackCommandLine(); - } - } - - vfunc_get_display_name() { - return this.name; - } - - vfunc_set_as_last_used_for_type() { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_SUPPORTED, 'Not supported'); - } - - vfunc_get_supported_types() { - return []; - } - - _getFallbackCommandLine() { - return `gio open ${this.location?.get_uri()}`; - } - - async _queryLocationIcons(params) { - const icons = {standard: null, custom: null}; - if (!this.location) - return icons; - - const cancellable = params.cancellable ?? this.cancellable; - const iconsQuery = []; - if (params?.standard) - iconsQuery.push(Gio.FILE_ATTRIBUTE_STANDARD_ICON); - - if (params?.custom) - iconsQuery.push(ATTRIBUTE_METADATA_CUSTOM_ICON); - - if (!iconsQuery.length) - throw new Error('Invalid Query Location Icons parameters'); - - let info; - try { - if (!GJS_SUPPORTS_FILE_IFACE_PROMISES) { - Gio._promisify(this.location.constructor.prototype, - 'query_info_async', 'query_info_finish'); - } - info = await this.location.query_info_async( - iconsQuery.join(','), - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_LOW, cancellable); - if (info.has_attribute(Gio.FILE_ATTRIBUTE_STANDARD_ICON)) - icons.standard = info.get_icon(); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND) || - e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) - return icons; - throw e; - } - - const customIcon = info.get_attribute_string(ATTRIBUTE_METADATA_CUSTOM_ICON); - if (customIcon) { - const customIconFile = GLib.uri_parse_scheme(customIcon) - ? Gio.File.new_for_uri(customIcon) : Gio.File.new_for_path(customIcon); - const iconFileInfo = await customIconFile.query_info_async( - Gio.FILE_ATTRIBUTE_STANDARD_TYPE, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_LOW, cancellable); - - if (iconFileInfo.get_file_type() === Gio.FileType.REGULAR) - icons.custom = Gio.FileIcon.new(customIconFile); - } - - return icons; - } - - async _updateLocationIcon(params = {standard: true, custom: true}) { - const cancellable = new Utils.CancellableChild(this.cancellable); - - try { - this._updateIconCancellable?.cancel(); - this._updateIconCancellable = cancellable; - - const icons = await this._queryLocationIcons({cancellable, ...params}); - const icon = icons.custom ?? icons.standard; - - if (icon && !icon.equal(this.icon)) - this.icon = icon; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'Impossible to update icon for %s'.format(this.get_id())); - } finally { - cancellable.cancel(); - if (this._updateIconCancellable === cancellable) - delete this._updateIconCancellable; - } - } - - async _getHandlerAppAsync(cancellable) { - if (!this.location) - return null; - - try { - if (!GJS_SUPPORTS_FILE_IFACE_PROMISES) { - Gio._promisify(this.location.constructor.prototype, - 'query_default_handler_async', - 'query_default_handler_finish'); - } - - return await this.location.query_default_handler_async( - GLib.PRIORITY_DEFAULT, cancellable); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) - return getFileManagerApp()?.appInfo; - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - logError(e, 'Impossible to find an URI handler for %s'.format( - this.get_id())); - } - - throw e; - } - } - - _getHandlerAppFromWorker(cancellable) { - const locationsWorker = GLib.build_filenamev([ - Docking.DockManager.extension.path, - 'locationsWorker.js', - ]); - const locationsWorkerArgs = [LocationAppInfo.GJS_BINARY_PATH, '-m', - locationsWorker, 'handler', this.location.get_uri(), - '--timeout', `${LAUNCH_HANDLER_MAX_WAIT}`]; - const subProcess = Gio.Subprocess.new(locationsWorkerArgs, - Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE); - - try { - const [, stdOut, stdErr] = subProcess.communicate(null, cancellable); - subProcess.wait(cancellable); - const errorCode = subProcess.get_exit_status(); - const textDecoder = new TextDecoder(); - - if (errorCode) { - const errorLines = textDecoder.decode(stdErr.toArray()).split('\n'); - const error = new GLib.Error(Gio.IOErrorEnum, - errorCode === GLib.MAXUINT8 ? 0 : errorCode, errorLines[0]); - error.stack = `${errorLines.slice(3).join('\n')}${error.stack}`; - throw error; - } - - const desktopId = textDecoder.decode(stdOut.toArray()).trim(); - const handlerApp = Shell.AppSystem.get_default().lookup_app(desktopId)?.appInfo; - return handlerApp; - } finally { - subProcess.force_exit(); - } - } - - getHandlerApp() { - if (this._handlerApp) - return this._handlerApp; - - if (!this.location) - return null; - - const cancellable = new Utils.CancellableChild(this.cancellable); - - try { - if (LocationAppInfo.GJS_BINARY_PATH) - this._handlerApp = this._getHandlerAppFromWorker(cancellable); - else - this._handlerApp = this.location.query_default_handler(cancellable); - - if (!this._handlerApp) { - throw new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.NOT_FOUND, `Handler for ${this.location} not found`); - } - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) - return getFileManagerApp()?.appInfo; - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - logError(e, 'Impossible to find an URI handler for %s'.format( - this.get_id())); - } - - throw e; - } - - return this._handlerApp; - } - - destroy() { - this.location = null; - this.icon = null; - this.name = null; - this._handlerApp = null; - this.cancellable?.cancel(); - } -}); - -const MountableVolumeAppInfo = GObject.registerClass({ - Implements: [Gio.AppInfo], - Properties: { - 'volume': GObject.ParamSpec.object( - 'volume', 'volume', 'volume', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - Gio.Volume.$gtype), - 'mount': GObject.ParamSpec.object( - 'mount', 'mount', 'mount', - GObject.ParamFlags.READWRITE, - Gio.Mount.$gtype), - 'busy': GObject.ParamSpec.boolean( - 'busy', 'busy', 'busy', - GObject.ParamFlags.READWRITE, - false), - }, -}, -class MountableVolumeAppInfo extends LocationAppInfo { - _init(volume, cancellable = null) { - super._init({ - volume, - cancellable, - }); - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - - const updateAndMonitor = () => { - this._update(); - this._monitorChanges(); - }; - updateAndMonitor(); - this._mountChanged = this.connect('notify::mount', updateAndMonitor); - - if (!this.mount && this.volume.get_identifier('class') === 'network') { - // For some devices the mount point isn't advertised promptly - // even if it's already existing, and there's no signaling about - this._lazyUpdater = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 2, () => { - this._update(); - delete this._lazyUpdater; - return GLib.SOURCE_REMOVE; - }); - } - } - - get busy() { - return !!this._currentAction; - } - - get currentAction() { - return this._currentAction; - } - - destroy() { - if (this._lazyUpdater) { - GLib.source_remove(this._lazyUpdater); - delete this._lazyUpdater; - } - this.disconnect(this._mountChanged); - this.mount = null; - this._signalsHandler.destroy(); - - super.destroy(); - } - - vfunc_dup() { - return new MountableVolumeAppInfo({ - volume: this.volume, - cancellable: this.cancellable, - }); - } - - vfunc_get_id() { - const uuid = this.mount?.get_uuid() ?? this.volume.get_uuid(); - return uuid ? 'mountable-volume:%s'.format(uuid) : super.vfunc_get_id(); - } - - vfunc_equal(other) { - if (this.volume === other?.volume && this.mount === other?.mount) - return true; - - return this.get_id() === other?.get_id(); - } - - list_actions() { - const actions = []; - const {mount} = this; - - if (mount) { - if (this.mount.can_unmount()) - actions.push('unmount'); - if (this.mount.can_eject()) - actions.push('eject'); - - return actions; - } - - if (this.volume.can_mount()) - actions.push('mount'); - if (this.volume.can_eject()) - actions.push('eject'); - - return actions; - } - - get_action_name(action) { - switch (action) { - case 'mount': - return __('Mount'); - case 'unmount': - return __('Unmount'); - case 'eject': - return __('Eject'); - default: - return null; - } - } - - vfunc_launch(files, context) { - if (this.mount || files?.length) - return super.vfunc_launch(files, context); - - this.mountAndLaunch(files, context); - return true; - } - - _update() { - this.mount = this.volume.get_mount(); - - const removable = this.mount ?? this.volume; - this.name = removable.get_name(); - this.icon = removable.get_icon(); - - this.location = this.mount?.get_default_location() ?? - this.volume.get_activation_root(); - - this._updateLocationIcon({custom: true}); - } - - _monitorChanges() { - this._signalsHandler.destroy(); - - const removable = this.mount ?? this.volume; - this._signalsHandler.add(removable, 'changed', () => this._update()); - - if (this.mount) { - this._signalsHandler.add(this.mount, 'pre-unmount', () => this._update()); - this._signalsHandler.add(this.mount, 'unmounted', () => this._update()); - } - } - - async mountAndLaunch(files, context) { - if (this.mount) - return super.vfunc_launch(files, context); - - try { - await this.launchAction('mount'); - if (!this.mount) { - throw new Error('No mounted location to open for %s'.format( - this.get_id())); - } - - return super.vfunc_launch(files, context); - } catch (e) { - logError(e, 'Mount and launch %s'.format(this.get_id())); - return false; - } - } - - _notifyActionError(action, message) { - if (action === 'mount') { - global.notify_error(__('Failed to mount “%s”'.format( - this.get_name())), message); - } else if (action === 'unmount') { - global.notify_error(__('Failed to umount “%s”'.format( - this.get_name())), message); - } else if (action === 'eject') { - global.notify_error(__('Failed to eject “%s”'.format( - this.get_name())), message); - } - } - - async launchAction(action) { - if (!this.list_actions().includes(action)) - throw new Error('Action %s is not supported by %s', action, this); - - if (this._currentAction) { - if (this._currentAction === 'mount') { - this._notifyActionError(action, - __('Mount operation already in progress')); - } else if (this._currentAction === 'unmount') { - this._notifyActionError(action, - __('Umount operation already in progress')); - } else if (this._currentAction === 'eject') { - this._notifyActionError(action, - __('Eject operation already in progress')); - } - - throw new Error('Another action %s is being performed in %s'.format( - this._currentAction, this)); - } - - this._currentAction = action; - this.notify('busy'); - const removable = this.mount ?? this.volume; - const operation = new ShellMountOperation.ShellMountOperation(removable); - try { - if (action === 'mount') { - await this.volume.mount(Gio.MountMountFlags.NONE, operation.mountOp, - this.cancellable); - } else if (action === 'unmount') { - await this.mount.unmount_with_operation(Gio.MountUnmountFlags.FORCE, - operation.mountOp, this.cancellable); - } else if (action === 'eject') { - await removable.eject_with_operation(Gio.MountUnmountFlags.FORCE, - operation.mountOp, this.cancellable); - } else { - logError(new Error(), 'No action %s on removable %s'.format(action, - removable.get_name())); - return false; - } - - return true; - } catch (e) { - if (action === 'mount' && - e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.ALREADY_MOUNTED)) - return true; - else if (action === 'umount' && - e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) - return true; - - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED)) - this._notifyActionError(action, e.message); - - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - logError(e, 'Impossible to %s removable %s'.format(action, - removable.get_name())); - } - - return false; - } finally { - delete this._currentAction; - this.notify('busy'); - this._update(); - operation.close(); - } - } -}); - -const TrashAppInfo = GObject.registerClass({ - Implements: [Gio.AppInfo], - Properties: { - 'empty': GObject.ParamSpec.boolean( - 'empty', 'empty', 'empty', - GObject.ParamFlags.READWRITE, - true), - }, -}, -class TrashAppInfo extends LocationAppInfo { - static initPromises(file) { - if (TrashAppInfo._promisified) - return; - - const trashProto = file.constructor.prototype; - Gio._promisify(Gio.FileEnumerator.prototype, 'close_async', 'close_finish'); - Gio._promisify(Gio.FileEnumerator.prototype, 'next_files_async', 'next_files_finish'); - Gio._promisify(trashProto, 'enumerate_children_async', 'enumerate_children_finish'); - Gio._promisify(trashProto, 'query_info_async', 'query_info_finish'); - TrashAppInfo._promisified = true; - } - - _init(cancellable = null) { - super._init({ - location: Gio.file_new_for_uri(TRASH_URI), - name: __('Trash'), - icon: Gio.ThemedIcon.new(FALLBACK_TRASH_ICON), - cancellable, - }); - TrashAppInfo.initPromises(this.location); - - try { - this._monitor = this.location.monitor_directory(0, this.cancellable); - this._schedUpdateId = 0; - this._monitorChangedId = this._monitor.connect('changed', () => - this._onTrashChange()); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - return; - logError(e, 'Impossible to monitor trash'); - } - this._updateTrash(); - - this.connect('notify::empty', () => this._updateLocationIcon()); - this.notify('empty'); - } - - destroy() { - if (this._schedUpdateId) { - GLib.source_remove(this._schedUpdateId); - this._schedUpdateId = 0; - } - this._updateTrashCancellable?.cancel(); - this._monitor?.disconnect(this._monitorChangedId); - this._monitor = null; - - super.destroy(); - } - - list_actions() { - return this.empty ? [] : ['empty-trash']; - } - - get_action_name(action) { - switch (action) { - case 'empty-trash': - return __('Empty Trash'); - default: - return null; - } - } - - _onTrashChange() { - if (this._schedUpdateId) { - GLib.source_remove(this._schedUpdateId); - this._schedUpdateId = 0; - } - - if (this._monitor.is_cancelled()) - return; - - this._schedUpdateId = GLib.timeout_add(GLib.PRIORITY_LOW, - UPDATE_TRASH_DELAY, () => { - this._schedUpdateId = 0; - this._updateTrash(); - return GLib.SOURCE_REMOVE; - }); - } - - async _updateTrash() { - const priority = GLib.PRIORITY_LOW; - this._updateTrashCancellable?.cancel(); - const cancellable = new Utils.CancellableChild(this.cancellable); - this._updateTrashCancellable = cancellable; - - try { - const trashInfo = await this.location.query_info_async( - Gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT, - Gio.FileQueryInfoFlags.NONE, - priority, cancellable); - this.empty = !trashInfo.get_attribute_uint32( - Gio.FILE_ATTRIBUTE_TRASH_ITEM_COUNT); - return; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'Impossible to get trash children from infos'); - } finally { - cancellable.cancel(); - if (this._updateIconCancellable === cancellable) - delete this._updateTrashCancellable; - } - - try { - const childrenEnumerator = await this.location.enumerate_children_async( - Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, - priority, cancellable); - const children = await childrenEnumerator.next_files_async(1, - priority, cancellable); - this.empty = !children.length; - - await childrenEnumerator.close_async(priority, null); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e, 'Impossible to enumerate trash children'); - } finally { - cancellable.cancel(); - if (this._updateIconCancellable === cancellable) - delete this._updateTrashCancellable; - } - } - - launchAction(action, timestamp) { - if (!this.list_actions().includes(action)) - throw new Error('Action %s is not supported by %s', action, this); - - const nautilus = makeNautilusFileOperationsProxy(); - const askConfirmation = true; - nautilus.EmptyTrashRemote(askConfirmation, - nautilus.platformData({timestamp}), (_p, error) => { - if (error) - logError(error, 'Empty trash failed'); - }, this.cancellable); - } -}); - -/** - * @param shellApp - */ -function wrapWindowsBackedApp(shellApp) { - if (shellApp._dtdData) - throw new Error('%s has been already wrapped'.format(shellApp)); - - shellApp._dtdData = { - windows: [], - state: undefined, - startingWorkspace: 0, - isFocused: false, - proxyProperties: [], - sources: new Set(), - signalConnections: new Utils.GlobalSignalsHandler(), - methodInjections: new Utils.InjectionsHandler(), - propertyInjections: new Utils.PropertyInjectionsHandler(), - addProxyProperties(parent, proxyProperties) { - Object.entries(proxyProperties).forEach(([p, o]) => { - const publicProp = o.public ? p : `_${p}`; - const get = o.getter && o.value instanceof Function - ? () => this[p]() : () => this[p]; - Object.defineProperty(parent, publicProp, Object.assign({ - get, - set: v => (this[p] = v), - configurable: true, - enumerable: !!o.enumerable, - }, o.readOnly ? {set: undefined} : {})); - if (o.value) - this[p] = o.value; - this.proxyProperties.push(publicProp); - }); - }, - destroy() { - this.windows = []; - this.proxyProperties = []; - this.sources.forEach(s => GLib.source_remove(s)); - this.sources.clear(); - this.signalConnections.destroy(); - this.methodInjections.destroy(); - this.propertyInjections.destroy(); - }, - }; - - shellApp._dtdData.addProxyProperties(shellApp, { - windows: {}, - state: {}, - startingWorkspace: {}, - isFocused: {public: true}, - signalConnections: {readOnly: true}, - sources: {readOnly: true}, - checkFocused: {}, - setDtdData: {}, - }); - - shellApp._setDtdData = function (data, params = {}) { - for (const [name, value] of Object.entries(data)) { - if (params.readOnly && name in this._dtdData) - throw new Error('Property %s is already defined'.format(name)); - const defaultParams = {public: true, readOnly: true}; - this._dtdData.addProxyProperties(this, { - [name]: {...defaultParams, ...params, value}, - }); - } - }; - - const m = (...args) => shellApp._dtdData.methodInjections.add(shellApp, ...args); - const p = (...args) => shellApp._dtdData.propertyInjections.add(shellApp, ...args); - - // mi is Method injector, pi is Property injector - shellApp._setDtdData({mi: m, pi: p}, {public: false}); - - m('get_state', () => shellApp._state ?? shellApp._getStateByWindows()); - p('state', {get: () => shellApp.get_state()}); - - m('get_windows', () => shellApp._windows); - m('get_n_windows', () => shellApp._windows.length); - m('get_pids', () => shellApp._windows.reduce((pids, w) => { - if (w.get_pid() > 0 && !pids.includes(w.get_pid())) - pids.push(w.get_pid()); - return pids; - }, [])); - m('is_on_workspace', (_om, workspace) => shellApp._windows.some(w => - w.get_workspace() === workspace) || - (shellApp.state === Shell.AppState.STARTING && - [-1, workspace.index()].includes(shellApp._startingWorkspace))); - m('request_quit', () => shellApp._windows.filter(w => - w.can_close()).forEach(w => w.delete(global.get_current_time()))); - - shellApp._setDtdData({ - _getStateByWindows() { - return this.get_n_windows() ? Shell.AppState.RUNNING : Shell.AppState.STOPPED; - }, - - _updateWindows() { - throw new GObject.NotImplementedError(`_updateWindows in ${this.constructor.name}`); - }, - - _notifyStateChanged() { - Shell.AppSystem.get_default().emit('app-state-changed', this); - this.notify('state'); - }, - - _setState(state) { - const oldState = this.state; - this._state = state; - - if (this.state !== oldState) - this._notifyStateChanged(); - }, - - _setWindows(windows) { - const oldState = this.state; - const oldWindows = this._windows.slice(); - const result = {windowsChanged: false, stateChanged: false}; - this._state = undefined; - - if (windows.length !== oldWindows.length || - windows.some((win, index) => win !== oldWindows[index])) { - this._windows = windows.filter(w => !w.is_override_redirect()); - this.emit('windows-changed'); - result.windowsChanged = true; - } - - if (this.state !== oldState) { - this._notifyStateChanged(); - this._checkFocused(); - result.stateChanged = true; - } - - return result; - }, - }, {readOnly: false}); - - shellApp._sources.add(GLib.idle_add(GLib.DEFAULT_PRIORITY, () => { - shellApp._updateWindows(); - shellApp._sources.delete(GLib.main_current_source().source_id); - return GLib.SOURCE_REMOVE; - })); - - const windowTracker = Shell.WindowTracker.get_default(); - shellApp._checkFocused = function () { - if (this._windows.some(w => w.has_focus())) { - this.isFocused = true; - windowTracker.notify('focus-app'); - } else if (this.isFocused) { - this.isFocused = false; - windowTracker.notify('focus-app'); - } - }; - - shellApp._checkFocused(); - shellApp._signalConnections.add(global.display, 'notify::focus-window', () => - shellApp._checkFocused()); - - // Re-implements shell_app_activate_window for generic activation and alt-tab support - m('activate_window', function (_om, window, timestamp) { - /* eslint-disable no-invalid-this */ - if (!window) - [window] = this.get_windows(); - else if (!this._windows.includes(window)) - return; - - const currentWorkspace = global.workspace_manager.get_active_workspace(); - const workspace = window.get_workspace(); - const sameWorkspaceWindows = this.get_windows().filter(w => - w.get_workspace() === workspace); - sameWorkspaceWindows.forEach(w => w.raise()); - - if (workspace !== currentWorkspace) - workspace.activate_with_focus(window, timestamp); - else - window.activate(timestamp); - /* eslint-enable no-invalid-this */ - }); - - // Re-implements shell_app_activate_full for generic activation and dash support - m('activate_full', function (_om, workspace, timestamp) { - /* eslint-disable no-invalid-this */ - if (!timestamp) - timestamp = global.get_current_time(); - - switch (this.state) { - case Shell.AppState.STOPPED: - try { - this._startingWorkspace = workspace; - this._setState(Shell.AppState.STARTING); - this.launch(timestamp, workspace, Shell.AppLaunchGpu.APP_PREF); - } catch (e) { - logError(e); - this._setState(Shell.AppState.STOPPED); - global.notify_error(_('Failed to launch “%s”'.format( - this.get_name())), e.message); - } - break; - case Shell.AppState.RUNNING: - this.activate_window(null, timestamp); - break; - } - /* eslint-enable no-invalid-this */ - }); - - m('activate', () => shellApp.activate_full(-1, 0)); - - m('compare', (_om, other) => Utils.shellAppCompare(shellApp, other)); - - const {destroy: defaultDestroy} = shellApp; - shellApp.destroy = function () { - /* eslint-disable no-invalid-this */ - this._dtdData.proxyProperties.forEach(prop => delete this[prop]); - this._dtdData.destroy(); - this._dtdData = undefined; - this.appInfo.destroy?.(); - this.destroy = defaultDestroy; - defaultDestroy?.call(this); - /* eslint-enable no-invalid-this */ - }; - - return shellApp; -} - -/** - * We can't inherit from Shell.App as it's a final type, so let's patch it - * - * @param params - */ -function makeLocationApp(params) { - if (!(params?.appInfo instanceof LocationAppInfo)) - throw new TypeError('Invalid location'); - - const {fallbackIconName} = params; - delete params.fallbackIconName; - - const shellApp = new Shell.App(params); - wrapWindowsBackedApp(shellApp); - - shellApp._setDtdData({ - location: () => shellApp.appInfo.location, - isTrash: shellApp.appInfo instanceof TrashAppInfo, - }, {getter: true, enumerable: true}); - - shellApp._mi('toString', defaultToString => - '[LocationApp "%s" - %s]'.format(shellApp.get_id(), - defaultToString.call(shellApp))); - - shellApp._mi('launch', (_om, timestamp, workspace, _gpuPref) => - shellApp.appInfo.launch([], - global.create_app_launch_context(timestamp, workspace))); - - shellApp._mi('launch_action', (_om, actionName, ...args) => - shellApp.appInfo.launchAction(actionName, ...args)); - - shellApp._mi('create_icon_texture', (_om, iconSize) => new St.Icon({ - iconSize, - gicon: shellApp.icon, - fallbackIconName, - })); - - // FIXME: We need to add a new API to Nautilus to open new windows - shellApp._mi('can_open_new_window', () => { - try { - if (!shellApp.get_n_windows()) - return true; - - const handlerApp = shellApp.appInfo.getHandlerApp(); - - if (handlerApp.has_key('SingleMainWindow')) - return !handlerApp.get_boolean('SingleMainWindow'); - - if (handlerApp.has_key('X-GNOME-SingleWindow')) - return !handlerApp.get_boolean('X-GNOME-SingleWindow'); - - if (handlerApp.get_commandline()?.split(' ').includes('--new-window')) - return true; - - const [window] = shellApp.get_windows(); - if (window && window.get_gtk_window_object_path()) - return window.get_gtk_application_id() === null; - - return true; - } catch { - return false; - } - }); - - shellApp._mi('open_new_window', function (_om, workspace) { - /* eslint-disable no-invalid-this */ - const context = global.create_app_launch_context(0, workspace); - if (!this.get_n_windows()) { - this.appInfo.launch([], context); - return; - } - const appId = this.appInfo.get_id(); - Gio.AppInfo.create_from_commandline(this.appInfo.get_commandline(), - this.appInfo.get_id(), appId - ? Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION - : Gio.AppInfoCreateFlags.NONE).launch_uris( - [this.appInfo.location.get_uri()], context); - /* eslint-enable no-invalid-this */ - }); - - if (shellApp.appInfo instanceof MountableVolumeAppInfo) { - shellApp._mi('get_busy', function (parentGetBusy) { - /* eslint-disable no-invalid-this */ - if (this.appInfo.busy) - return true; - return parentGetBusy.call(this); - /* eslint-enable no-invalid-this */ - }); - shellApp._pi('busy', {get: () => shellApp.get_busy()}); - shellApp._signalConnections.add(shellApp.appInfo, 'notify::busy', _ => - shellApp.notify('busy')); - } - - shellApp._mi('get_windows', function () { - /* eslint-disable no-invalid-this */ - if (this._needsResort) - this._sortWindows(); - return this._windows; - /* eslint-enable no-invalid-this */ - }); - - const {fm1Client} = Docking.DockManager.getDefault(); - shellApp._setDtdData({ - _needsResort: true, - - _windowsOrderChanged() { - this._needsResort = true; - this.emit('windows-changed'); - }, - - _sortWindows() { - this._windows.sort(Utils.shellWindowsCompare); - this._needsResort = false; - }, - - _updateWindows() { - const windows = fm1Client.getWindows(this.location?.get_uri()).sort( - Utils.shellWindowsCompare); - const {windowsChanged} = this._setWindows(windows); - - if (!windowsChanged) - return; - - this._signalConnections.removeWithLabel(Labels.LOCATION_WINDOWS); - windows.forEach(w => - this._signalConnections.addWithLabel(Labels.LOCATION_WINDOWS, w, - 'notify::user-time', () => { - if (w !== this._windows[0]) - this._windowsOrderChanged(); - })); - }, - }, {readOnly: false}); - - shellApp._signalConnections.add(fm1Client, 'windows-changed', () => - shellApp._updateWindows()); - shellApp._signalConnections.add(shellApp.appInfo, 'notify::icon', () => - shellApp.notify('icon')); - shellApp._signalConnections.add(global.workspaceManager, - 'workspace-switched', () => shellApp._windowsOrderChanged()); - - return shellApp; -} - -/** - * - */ -function getFileManagerApp() { - return Shell.AppSystem.get_default().lookup_app(FILE_MANAGER_DESKTOP_APP_ID); -} - -/** - * - */ -export function wrapFileManagerApp() { - const fileManagerApp = getFileManagerApp(); - if (!fileManagerApp) - return null; - - if (fileManagerApp._dtdData) - return fileManagerApp; - - const originalGetWindows = fileManagerApp.get_windows; - wrapWindowsBackedApp(fileManagerApp); - - const {removables, trash} = Docking.DockManager.getDefault(); - fileManagerApp._signalConnections.addWithLabel(Labels.WINDOWS_CHANGED, - fileManagerApp, 'windows-changed', () => { - fileManagerApp.stop_emission_by_name('windows-changed'); - // Let's wait for the location app to take control before of us - const id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 50, () => { - fileManagerApp._sources.delete(id); - fileManagerApp._updateWindows(); - return GLib.SOURCE_REMOVE; - }); - fileManagerApp._sources.add(id); - }); - - fileManagerApp._signalConnections.add(global.workspaceManager, - 'workspace-switched', () => { - fileManagerApp._signalConnections.blockWithLabel(Labels.WINDOWS_CHANGED); - fileManagerApp.emit('windows-changed'); - fileManagerApp._signalConnections.unblockWithLabel(Labels.WINDOWS_CHANGED); - }); - - if (removables) { - fileManagerApp._signalConnections.add(removables, 'changed', () => - fileManagerApp._updateWindows()); - fileManagerApp._signalConnections.add(removables, 'windows-changed', () => - fileManagerApp._updateWindows()); - } - - if (trash?.getApp()) { - fileManagerApp._signalConnections.add(trash.getApp(), 'windows-changed', () => - fileManagerApp._updateWindows()); - } - - fileManagerApp._updateWindows = function () { - const locationWindows = []; - getRunningApps().forEach(a => locationWindows.push(...a.get_windows())); - const windows = originalGetWindows.call(this).filter(w => - !locationWindows.includes(w)); - - this._signalConnections.blockWithLabel(Labels.WINDOWS_CHANGED); - this._setWindows(windows); - this._signalConnections.unblockWithLabel(Labels.WINDOWS_CHANGED); - }; - - fileManagerApp._mi('toString', defaultToString => - '[FileManagerApp - %s]'.format(defaultToString.call(fileManagerApp))); - - return fileManagerApp; -} - -/** - * - */ -export function unWrapFileManagerApp() { - const fileManagerApp = getFileManagerApp(); - if (!fileManagerApp || !fileManagerApp._dtdData) - return; - - fileManagerApp.destroy(); -} - -/** - * This class maintains a Shell.App representing the Trash and keeps it - * up-to-date as the trash fills and is emptied over time. - */ -export class Trash { - destroy() { - this._trashApp?.destroy(); - } - - _ensureApp() { - if (this._trashApp) - return; - - this._trashApp = makeLocationApp({ - appInfo: new TrashAppInfo(new Gio.Cancellable()), - fallbackIconName: FALLBACK_TRASH_ICON, - }); - } - - getApp() { - this._ensureApp(); - return this._trashApp; - } -} - -/** - * This class maintains Shell.App representations for removable devices - * plugged into the system, and keeps the list of Apps up-to-date as - * devices come and go and are mounted and unmounted. - */ -export class Removables { - static initVolumePromises(object) { - // TODO: This can be simplified using actual interface type when we - // can depend on gjs 1.72 - if (!(object instanceof Gio.Volume) || object.constructor.prototype._d2dPromisified) - return; - - Gio._promisify(object.constructor.prototype, 'mount', 'mount_finish'); - Gio._promisify(object.constructor.prototype, 'eject_with_operation', - 'eject_with_operation_finish'); - object.constructor.prototype._d2dPromisified = true; - } - - static initMountPromises(object) { - // TODO: This can be simplified using actual interface type when we - // can depend on gjs 1.72 - if (!(object instanceof Gio.Mount) || object.constructor.prototype._d2dPromisified) - return; - - Gio._promisify(object.constructor.prototype, 'eject_with_operation', - 'eject_with_operation_finish'); - Gio._promisify(object.constructor.prototype, 'unmount_with_operation', - 'unmount_with_operation_finish'); - object.constructor.prototype._d2dPromisified = true; - } - - constructor() { - this._signalsHandler = new Utils.GlobalSignalsHandler(); - - this._monitor = Gio.VolumeMonitor.get(); - this._cancellable = new Gio.Cancellable(); - - this._monitor.get_mounts().forEach(m => Removables.initMountPromises(m)); - this._updateVolumes(); - - this._signalsHandler.add([ - this._monitor, - 'volume-added', - (_, volume) => this._onVolumeAdded(volume), - ], [ - this._monitor, - 'volume-removed', - (_, volume) => this._onVolumeRemoved(volume), - ], [ - this._monitor, - 'mount-added', - (_, mount) => this._onMountAdded(mount), - ], [ - Docking.DockManager.settings, - 'changed::show-mounts-only-mounted', - () => this._updateVolumes(), - ], [ - Docking.DockManager.settings, - 'changed::show-mounts-network', - () => this._updateVolumes(), - ]); - } - - destroy() { - this._volumeApps.forEach(a => a.destroy()); - this._volumeApps = []; - this._cancellable.cancel(); - this._cancellable = null; - this._signalsHandler.destroy(); - this._monitor = null; - } - - _updateVolumes() { - this._volumeApps?.forEach(a => a.destroy()); - this._volumeApps = []; - this.emit('changed'); - - this._monitor.get_volumes().forEach(v => this._onVolumeAdded(v)); - } - - _onVolumeAdded(volume) { - Removables.initVolumePromises(volume); - - if (!Docking.DockManager.settings.showMountsNetwork && - volume.get_identifier('class') === 'network') - return; - - - const mount = volume.get_mount(); - if (mount) { - if (mount.is_shadowed()) - return; - if (!mount.can_eject() && !mount.can_unmount()) - return; - } else { - if (Docking.DockManager.settings.showMountsOnlyMounted) - return; - if (!volume.can_mount() && !volume.can_eject()) - return; - } - - const appInfo = new MountableVolumeAppInfo(volume, - new Utils.CancellableChild(this._cancellable)); - const volumeApp = makeLocationApp({ - appInfo, - fallbackIconName: FALLBACK_REMOVABLE_MEDIA_ICON, - }); - - volumeApp._signalConnections.add(volumeApp, 'windows-changed', - () => this.emit('windows-changed', volumeApp)); - - if (Docking.DockManager.settings.showMountsOnlyMounted) { - volumeApp._signalConnections.add(appInfo, 'notify::mount', - () => !appInfo.mount && this._onVolumeRemoved(appInfo.volume)); - } - - this._volumeApps.push(volumeApp); - this.emit('changed'); - } - - _onVolumeRemoved(volume) { - const volumeIndex = this._volumeApps.findIndex(({appInfo}) => - appInfo.volume === volume); - if (volumeIndex !== -1) { - const [volumeApp] = this._volumeApps.splice(volumeIndex, 1); - // We don't care about cancelling the ongoing operations from now on. - volumeApp.appInfo.cancellable = null; - volumeApp.destroy(); - this.emit('changed'); - } - } - - _onMountAdded(mount) { - Removables.initMountPromises(mount); - - if (!Docking.DockManager.settings.showMountsOnlyMounted) - return; - - if (!this._volumeApps.find(({appInfo}) => appInfo.mount === mount)) { - // In some Gio.Mount implementations the volume may be set after - // mount is emitted, so we could just ignore it as we'll get it - // later via volume-added - const volume = mount.get_volume(); - if (volume) - this._onVolumeAdded(volume); - } - } - - getApps() { - return this._volumeApps; - } -} -Signals.addSignalMethods(Removables.prototype); - -/** - * - */ -function getApps() { - const dockManager = Docking.DockManager.getDefault(); - const locationApps = []; - - if (dockManager.removables) - locationApps.push(...dockManager.removables.getApps()); - - if (dockManager.trash) - locationApps.push(dockManager.trash.getApp()); - - return locationApps; -} - -/** - * - */ -export function getRunningApps() { - return getApps().filter(a => a.state === Shell.AppState.RUNNING); -} - -/** - * - */ -export function getStartingApps() { - return getApps().filter(a => a.state === Shell.AppState.STARTING); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locationsWorker.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locationsWorker.js deleted file mode 100755 index 054c92c4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/locationsWorker.js +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env gjs - -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; - -const GJS_SUPPORTS_FILE_IFACE_PROMISES = imports.system.version >= 17101; - -if (GJS_SUPPORTS_FILE_IFACE_PROMISES) - Gio._promisify(Gio.File.prototype, 'query_default_handler_async'); - -function getHandlerAppAsync(location, cancellable) { - if (!location) - return null; - - if (!GJS_SUPPORTS_FILE_IFACE_PROMISES) { - Gio._promisify(location.constructor.prototype, - 'query_default_handler_async', - 'query_default_handler_finish'); - } - - return location.query_default_handler_async( - GLib.PRIORITY_DEFAULT, cancellable); -} - -async function mainAsync(argv) { - if (argv.length < 1) { - const currentBinary = GLib.path_get_basename(new Error().fileName); - printerr(`Usage: ${currentBinary} uri [ --timeout ]`); - return 1; - } - - const [action, uri] = argv; - let timeout = 200; - - if (action !== 'handler') - throw new TypeError(`Unexpected action ${action}`); - - for (let i = 1; i < argv.length; ++i) { - if (argv[i] === '--timeout' && i < argv.length - 1) - timeout = argv[++i]; - } - - const location = Gio.File.new_for_uri(uri); - const cancellable = new Gio.Cancellable(); - - // GVfs providers could hang when querying the file information, so we - // workaround this by using the async API in a sync way, but we need to - // use a timeout to avoid this to hang forever, better than hang the - // shell. - let launchMaxWaitId; - - try { - const handler = await Promise.race([ - getHandlerAppAsync(location, cancellable), - new Promise((_resolve, reject) => { - launchMaxWaitId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, timeout, () => { - launchMaxWaitId = 0; - cancellable.cancel(); - reject(new GLib.Error(Gio.IOErrorEnum, - Gio.IOErrorEnum.TIMED_OUT, - `Searching for ${location.get_uri()} ` + - 'handler took too long')); - return GLib.SOURCE_REMOVE; - }); - }), - ]); - - print(handler.get_id()); - } catch (e) { - printerr(e.message); - logError(e); - return e.code ? e.code : GLib.MAXUINT8; - } finally { - if (launchMaxWaitId) - GLib.source_remove(launchMaxWaitId); - } - - return 0; -} - -function main(args) { - let ret; - const loop = new GLib.MainLoop(null, false); - mainAsync(args).then(r => (ret = r)).catch(logError).finally(() => loop.quit()); - loop.run(); - - return ret; -} - -imports.system.exit(main(ARGV)); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/glossy.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/glossy.svg deleted file mode 100755 index 55b71baa..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/glossy.svg +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/highlight_stacked_bg.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/highlight_stacked_bg.svg deleted file mode 100755 index 19be5a9d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/highlight_stacked_bg.svg +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/highlight_stacked_bg_h.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/highlight_stacked_bg_h.svg deleted file mode 100755 index eeaa8691..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/highlight_stacked_bg_h.svg +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/logo.svg deleted file mode 100755 index eebd0b1d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/media/logo.svg +++ /dev/null @@ -1,528 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Dash to Dock - Michele - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/metadata.json deleted file mode 100755 index cd7451c0..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/metadata.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "A dock for the Gnome Shell. This extension moves the dash out of the overview transforming it in a dock for an easier launching of applications and a faster switching between windows and desktops. Side and bottom placement options are available.", - "gettext-domain": "dashtodock", - "name": "Dash to Dock", - "original-author": "micxgx@gmail.com", - "shell-version": [ - "45", - "46" - ], - "url": "https://micheleg.github.io/dash-to-dock/", - "uuid": "dash-to-dock@micxgx.gmail.com", - "version": 92 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/notificationsMonitor.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/notificationsMonitor.js deleted file mode 100755 index c9060e12..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/notificationsMonitor.js +++ /dev/null @@ -1,120 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import {Gio} from './dependencies/gi.js'; -import {Main} from './dependencies/shell/ui.js'; - -import { - Docking, - Utils, -} from './imports.js'; - -const {signals: Signals} = imports; - -const Labels = Object.freeze({ - SOURCES: Symbol('sources'), - NOTIFICATIONS: Symbol('notifications'), -}); -export class NotificationsMonitor { - constructor() { - this._settings = new Gio.Settings({ - schema_id: 'org.gnome.desktop.notifications', - }); - - this._appNotifications = Object.create(null); - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - - const getIsEnabled = () => !this.dndMode && - Docking.DockManager.settings.showIconsNotificationsCounter; - - this._isEnabled = getIsEnabled(); - const checkIsEnabled = () => { - const isEnabled = getIsEnabled(); - if (isEnabled !== this._isEnabled) { - this._isEnabled = isEnabled; - this.emit('state-changed'); - - this._updateState(); - } - }; - - this._dndMode = !this._settings.get_boolean('show-banners'); - this._signalsHandler.add(this._settings, 'changed::show-banners', () => { - this._dndMode = !this._settings.get_boolean('show-banners'); - checkIsEnabled(); - }); - this._signalsHandler.add(Docking.DockManager.settings, - 'changed::show-icons-notifications-counter', checkIsEnabled); - - this._updateState(); - } - - destroy() { - this.emit('destroy'); - this._signalsHandler.destroy(); - this._signalsHandler = null; - this._appNotifications = null; - this._settings = null; - } - - get enabled() { - return this._isEnabled; - } - - get dndMode() { - return this._dndMode; - } - - getAppNotificationsCount(appId) { - return this._appNotifications[appId] ?? 0; - } - - _updateState() { - if (this.enabled) { - this._signalsHandler.addWithLabel(Labels.SOURCES, Main.messageTray, - 'source-added', () => this._checkNotifications()); - this._signalsHandler.addWithLabel(Labels.SOURCES, Main.messageTray, - 'source-removed', () => this._checkNotifications()); - } else { - this._signalsHandler.removeWithLabel(Labels.SOURCES); - } - - this._checkNotifications(); - } - - _checkNotifications() { - this._appNotifications = Object.create(null); - this._signalsHandler.removeWithLabel(Labels.NOTIFICATIONS); - - if (this.enabled) { - Main.messageTray.getSources().forEach(source => { - this._signalsHandler.addWithLabel(Labels.NOTIFICATIONS, source, - 'notification-added', () => this._checkNotifications()); - - source.notifications.forEach(notification => { - const app = notification.source?.app ?? notification.source?._app; - - if (app?.id) { - if (notification.resident) { - if (notification.acknowledged) - return; - - this._signalsHandler.addWithLabel(Labels.NOTIFICATIONS, - notification, 'notify::acknowledged', - () => this._checkNotifications()); - } - - this._signalsHandler.addWithLabel(Labels.NOTIFICATIONS, - notification, 'destroy', () => this._checkNotifications()); - - this._appNotifications[app.id] = - (this._appNotifications[app.id] ?? 0) + 1; - } - }); - }); - } - - this.emit('changed'); - } -} - -Signals.addSignalMethods(NotificationsMonitor.prototype); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/prefs.js deleted file mode 100755 index 110a1f7e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/prefs.js +++ /dev/null @@ -1,1172 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; - -import { - ExtensionPreferences, - - // Use __ () and N__() for the extension gettext domain, and reuse - // the shell domain with the default _() and N_() - gettext as __, -} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -const SCALE_UPDATE_TIMEOUT = 500; -const DEFAULT_ICONS_SIZES = [128, 96, 64, 48, 32, 24, 16]; - -const TransparencyMode = Object.freeze({ - DEFAULT: 0, - FIXED: 1, - DYNAMIC: 3, -}); - -const RunningIndicatorStyle = Object.freeze({ - DEFAULT: 0, - DOTS: 1, - SQUARES: 2, - DASHES: 3, - SEGMENTED: 4, - SOLID: 5, - CILIORA: 6, - METRO: 7, -}); - -const MonitorsConfig = GObject.registerClass({ - Signals: { - 'updated': {}, - }, -}, class MonitorsConfig extends GObject.Object { - static get XML_INTERFACE() { - return '\ - \ - \ - \ - \ - \ - \ - \ - \ - \ - '; - } - - static get ProxyWrapper() { - return Gio.DBusProxy.makeProxyWrapper(MonitorsConfig.XML_INTERFACE); - } - - constructor() { - super(); - - this._monitorsConfigProxy = new MonitorsConfig.ProxyWrapper( - Gio.DBus.session, - 'org.gnome.Mutter.DisplayConfig', - '/org/gnome/Mutter/DisplayConfig' - ); - - // Connecting to a D-Bus signal - this._monitorsConfigProxy.connectSignal('MonitorsChanged', - () => this._updateResources()); - - this._primaryMonitor = null; - this._monitors = []; - this._logicalMonitors = []; - - this._updateResources(); - } - - _updateResources() { - this._monitorsConfigProxy.GetCurrentStateRemote((resources, err) => { - if (err) { - logError(err); - return; - } - - const [serial_, monitors, logicalMonitors] = resources; - let index = 0; - for (const monitor of monitors) { - const [monitorSpecs, modes_, props] = monitor; - const [connector, vendor, product, serial] = monitorSpecs; - this._monitors.push({ - index: index++, - active: false, - connector, vendor, product, serial, - displayName: props['display-name'].unpack(), - }); - } - - for (const logicalMonitor of logicalMonitors) { - const [x_, y_, scale_, transform_, isPrimary, monitorsSpecs] = - logicalMonitor; - - // We only care about the first one really - for (const monitorSpecs of monitorsSpecs) { - const [connector, vendor, product, serial] = monitorSpecs; - const monitor = this._monitors.find(m => - m.connector === connector && m.vendor === vendor && - m.product === product && m.serial === serial); - - if (monitor) { - monitor.active = true; - monitor.isPrimary = isPrimary; - if (monitor.isPrimary) - this._primaryMonitor = monitor; - break; - } - } - } - - const activeMonitors = this._monitors.filter(m => m.active); - if (activeMonitors.length > 1 && logicalMonitors.length === 1) { - // We're in cloning mode, so let's just activate the primary monitor - this._monitors.forEach(m => (m.active = false)); - this._primaryMonitor.active = true; - } - - this._updateMonitorsIndexes(); - this.emit('updated'); - }); - } - - _updateMonitorsIndexes() { - // This function ensures that we follow the old Gdk indexing strategy - // for monitors, it can be removed when we don't care about breaking - // old user configurations or external apps configuring this extension - // such as ubuntu's gnome-control-center. - const {index: primaryMonitorIndex} = this._primaryMonitor; - for (const monitor of this._monitors) { - let {index} = monitor; - // The The dock uses the Gdk index for monitors, where the primary monitor - // always has index 0, so let's follow what dash-to-dock does in docking.js - // (as part of _createDocks), but using inverted math - index -= primaryMonitorIndex; - - if (index < 0) - index += this._monitors.length; - - monitor.index = index; - } - } - - get primaryMonitor() { - return this._primaryMonitor; - } - - get monitors() { - return this._monitors; - } -}); - -/** - * @param settings - */ -function setShortcut(settings) { - const shortcutText = settings.get_string('shortcut-text'); - const [success, key, mods] = Gtk.accelerator_parse(shortcutText); - - if (success && Gtk.accelerator_valid(key, mods)) { - const shortcut = Gtk.accelerator_name(key, mods); - settings.set_strv('shortcut', [shortcut]); - } else { - settings.set_strv('shortcut', []); - } -} - -const DockSettings = GObject.registerClass({ - Implements: [Gtk.BuilderScope], -}, class DashToDockSettings extends GObject.Object { - _init(extensionPreferences) { - super._init(); - - this._extensionPreferences = extensionPreferences; - this._settings = extensionPreferences.getSettings( - 'org.gnome.shell.extensions.dash-to-dock'); - this._appSwitcherSettings = new Gio.Settings({schema_id: 'org.gnome.shell.app-switcher'}); - this._rtl = Gtk.Widget.get_default_direction() === Gtk.TextDirection.RTL; - - this._builder = new Gtk.Builder(); - this._builder.set_scope(this); - this._builder.set_translation_domain( - extensionPreferences.metadata['gettext-domain']); - this._builder.add_from_file(`${extensionPreferences.path}/Settings.ui`); - - this.widget = this._builder.get_object('settings_notebook'); - - // Set a reasonable initial window height - this.widget.connect('realize', () => { - const rootWindow = this.widget.get_root(); - rootWindow.set_default_size(-1, 850); - rootWindow.connect('close-request', () => this._onWindowsClosed()); - }); - - // Timeout to delay the update of the settings - this._dock_size_timeout = 0; - this._icon_size_timeout = 0; - this._opacity_timeout = 0; - - this._monitorsConfig = new MonitorsConfig(); - this._bindSettings(); - } - - _onWindowsClosed() { - if (this._dock_size_timeout) { - GLib.source_remove(this._dock_size_timeout); - delete this._dock_size_timeout; - } - - if (this._icon_size_timeout) { - GLib.source_remove(this._icon_size_timeout); - delete this._icon_size_timeout; - } - - if (this._opacity_timeout) { - GLib.source_remove(this._opacity_timeout); - delete this._opacity_timeout; - } - } - - vfunc_create_closure(builder, handlerName, flags, connectObject) { - if (flags & Gtk.BuilderClosureFlags.SWAPPED) - throw new Error('Unsupported template signal flag "swapped"'); - - if (typeof this[handlerName] === 'undefined') - throw new Error(`${handlerName} is undefined`); - - return this[handlerName].bind(connectObject || this); - } - - dock_display_combo_changed_cb(combo) { - if (!this._monitors?.length || this._updatingSettings) - return; - - const preferredMonitor = this._monitors[combo.get_active()].connector; - - this._updatingSettings = true; - this._settings.set_string('preferred-monitor-by-connector', preferredMonitor); - this._settings.set_int('preferred-monitor', -2); - this._updatingSettings = false; - } - - position_top_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('dock-position', 0); - } - - position_right_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('dock-position', 1); - } - - position_bottom_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('dock-position', 2); - } - - position_left_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('dock-position', 3); - } - - icon_size_combo_changed_cb(combo) { - this._settings.set_int('dash-max-icon-size', this._allIconSizes[combo.get_active()]); - } - - dock_size_scale_value_changed_cb(scale) { - // Avoid settings the size continuously - if (this._dock_size_timeout > 0) - GLib.source_remove(this._dock_size_timeout); - this._dock_size_timeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._settings.set_double('height-fraction', scale.get_value()); - this._dock_size_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - icon_size_scale_value_changed_cb(scale) { - // Avoid settings the size consinuosly - if (this._icon_size_timeout > 0) - GLib.source_remove(this._icon_size_timeout); - this._icon_size_timeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._settings.set_int('dash-max-icon-size', scale.get_value()); - this._icon_size_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - preview_size_scale_format_value_cb(scale, value) { - return value === 0 ? 'auto' : value; - } - - preview_size_scale_value_changed_cb(scale) { - this._settings.set_double('preview-size-scale', scale.get_value()); - } - - custom_opacity_scale_value_changed_cb(scale) { - // Avoid settings the opacity consinuosly as it's change is animated - if (this._opacity_timeout > 0) - GLib.source_remove(this._opacity_timeout); - this._opacity_timeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._settings.set_double('background-opacity', scale.get_value()); - this._opacity_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - min_opacity_scale_value_changed_cb(scale) { - // Avoid settings the opacity consinuosly as it's change is animated - if (this._opacity_timeout > 0) - GLib.source_remove(this._opacity_timeout); - this._opacity_timeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._settings.set_double('min-alpha', scale.get_value()); - this._opacity_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - max_opacity_scale_value_changed_cb(scale) { - // Avoid settings the opacity consinuosly as it's change is animated - if (this._opacity_timeout > 0) - GLib.source_remove(this._opacity_timeout); - this._opacity_timeout = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, SCALE_UPDATE_TIMEOUT, () => { - this._settings.set_double('max-alpha', scale.get_value()); - this._opacity_timeout = 0; - return GLib.SOURCE_REMOVE; - }); - } - - all_windows_radio_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('intellihide-mode', 0); - } - - focus_application_windows_radio_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('intellihide-mode', 1); - } - - maximized_windows_radio_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('intellihide-mode', 2); - } - - always_on_top_radio_button_toggled_cb(button) { - if (button.get_active()) - this._settings.set_enum('intellihide-mode', 3); - } - - _updateMonitorsSettings() { - // Monitor options - const preferredMonitor = this._settings.get_int('preferred-monitor'); - const preferredMonitorByConnector = this._settings.get_string('preferred-monitor-by-connector'); - const dockMonitorCombo = this._builder.get_object('dock_monitor_combo'); - - this._monitors = []; - dockMonitorCombo.remove_all(); - let primaryIndex = -1; - - // Add connected monitors - for (const monitor of this._monitorsConfig.monitors) { - if (!monitor.active && monitor.index !== preferredMonitor) - continue; - - if (monitor.isPrimary) { - dockMonitorCombo.append_text( - /* Translators: This will be followed by Display Name - Connector. */ - `${__('Primary monitor: ') + monitor.displayName} - ${ - monitor.connector}`); - primaryIndex = this._monitors.length; - } else { - dockMonitorCombo.append_text( - /* Translators: Followed by monitor index, Display Name - Connector. */ - `${__('Secondary monitor ') + (monitor.index + 1)} - ${ - monitor.displayName} - ${monitor.connector}`); - } - - this._monitors.push(monitor); - - if (monitor.index === preferredMonitor || - (preferredMonitor === -2 && preferredMonitorByConnector === monitor.connector)) - dockMonitorCombo.set_active(this._monitors.length - 1); - } - - if (dockMonitorCombo.get_active() < 0 && primaryIndex >= 0) - dockMonitorCombo.set_active(primaryIndex); - } - - _bindSettings() { - // Position and size panel - - this._updateMonitorsSettings(); - this._monitorsConfig.connect('updated', - () => this._updateMonitorsSettings()); - this._settings.connect('changed::preferred-monitor', - () => this._updateMonitorsSettings()); - this._settings.connect('changed::preferred-monitor-by-connector', - () => this._updateMonitorsSettings()); - - // Position option - const position = this._settings.get_enum('dock-position'); - - switch (position) { - case 0: - this._builder.get_object('position_top_button').set_active(true); - break; - case 1: - this._builder.get_object('position_right_button').set_active(true); - break; - case 2: - this._builder.get_object('position_bottom_button').set_active(true); - break; - case 3: - this._builder.get_object('position_left_button').set_active(true); - break; - } - - if (this._rtl) { - /* Left is Right in rtl as a setting */ - this._builder.get_object('position_left_button').set_label(__('Right')); - this._builder.get_object('position_right_button').set_label(__('Left')); - } - - // Intelligent autohide options - this._settings.bind('dock-fixed', - this._builder.get_object('intelligent_autohide_switch'), - 'active', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - this._settings.bind('dock-fixed', - this._builder.get_object('intelligent_autohide_button'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - this._settings.bind('autohide', - this._builder.get_object('autohide_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('autohide-in-fullscreen', - this._builder.get_object('autohide_enable_in_fullscreen_checkbutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-dock-urgent-notify', - this._builder.get_object('show_dock_urgent_notify_checkbutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('require-pressure-to-show', - this._builder.get_object('require_pressure_checkbutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('intellihide', - this._builder.get_object('intellihide_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('animation-time', - this._builder.get_object('animation_duration_spinbutton'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('hide-delay', - this._builder.get_object('hide_timeout_spinbutton'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-delay', - this._builder.get_object('show_timeout_spinbutton'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('pressure-threshold', - this._builder.get_object('pressure_threshold_spinbutton'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - - // this._builder.get_object('animation_duration_spinbutton').set_value( - // this._settings.get_double('animation-time')); - - // Create dialog for intelligent autohide advanced settings - this._builder.get_object('intelligent_autohide_button').connect('clicked', () => { - const dialog = new Gtk.Dialog({ - title: __('Intelligent autohide customization'), - transient_for: this.widget.get_root(), - use_header_bar: true, - modal: true, - }); - - // GTK+ leaves positive values for application-defined response ids. - // Use +1 for the reset action - dialog.add_button(__('Reset to defaults'), 1); - - const box = this._builder.get_object('intelligent_autohide_advanced_settings_box'); - dialog.get_content_area().append(box); - - this._settings.bind('intellihide', - this._builder.get_object('intellihide_mode_box'), - 'sensitive', - Gio.SettingsBindFlags.GET); - - // intellihide mode - - const intellihideModeRadioButtons = [ - this._builder.get_object('all_windows_radio_button'), - this._builder.get_object('focus_application_windows_radio_button'), - this._builder.get_object('maximized_windows_radio_button'), - this._builder.get_object('always_on_top_radio_button'), - ]; - - intellihideModeRadioButtons[this._settings.get_enum('intellihide-mode')].set_active(true); - - this._settings.bind('autohide', - this._builder.get_object('require_pressure_checkbutton'), - 'sensitive', - Gio.SettingsBindFlags.GET); - - this._settings.bind('autohide', - this._builder.get_object('autohide_enable_in_fullscreen_checkbutton'), - 'sensitive', - Gio.SettingsBindFlags.GET); - - this._settings.bind('autohide', - this._builder.get_object('show_dock_urgent_notify_checkbutton'), - 'sensitive', - Gio.SettingsBindFlags.GET); - - this._settings.bind('require-pressure-to-show', - this._builder.get_object('show_timeout_spinbutton'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - this._settings.bind('require-pressure-to-show', - this._builder.get_object('show_timeout_label'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - this._settings.bind('require-pressure-to-show', - this._builder.get_object('pressure_threshold_spinbutton'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('require-pressure-to-show', - this._builder.get_object('pressure_threshold_label'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - dialog.connect('response', (_, id) => { - if (id === 1) { - // restore default settings for the relevant keys - const keys = ['intellihide', 'autohide', 'intellihide-mode', - 'autohide-in-fullscreen', 'show-dock-urgent-notify', - 'require-pressure-to-show', 'animation-time', - 'show-delay', 'hide-delay', 'pressure-threshold']; - keys.forEach(function (val) { - this._settings.set_value(val, this._settings.get_default_value(val)); - }, this); - intellihideModeRadioButtons[this._settings.get_enum('intellihide-mode')].set_active(true); - } else { - // remove the settings box so it doesn't get destroyed; - dialog.get_content_area().remove(box); - dialog.destroy(); - } - }); - - dialog.present(); - }); - - // size options - const dockSizeScale = this._builder.get_object('dock_size_scale'); - dockSizeScale.set_value(this._settings.get_double('height-fraction')); - dockSizeScale.add_mark(0.9, Gtk.PositionType.TOP, null); - dockSizeScale.set_format_value_func((_, value) => { - return `${Math.round(value * 100)} %`; - }); - const iconSizeScale = this._builder.get_object('icon_size_scale'); - iconSizeScale.set_range(8, DEFAULT_ICONS_SIZES[0]); - iconSizeScale.set_value(this._settings.get_int('dash-max-icon-size')); - DEFAULT_ICONS_SIZES.forEach(val => { - iconSizeScale.add_mark(val, Gtk.PositionType.TOP, val.toString()); - }); - iconSizeScale.set_format_value_func((_, value) => { - return `${value} px`; - }); - this._builder.get_object('preview_size_scale').set_value( - this._settings.get_double('preview-size-scale')); - - // Corrent for rtl languages - if (this._rtl) { - // Flip value position: this is not done automatically - dockSizeScale.set_value_pos(Gtk.PositionType.LEFT); - iconSizeScale.set_value_pos(Gtk.PositionType.LEFT); - // I suppose due to a bug, having a more than one mark and one above - // a value of 100 makes the rendering of the marks wrong in rtl. - // This doesn't happen setting the scale as not flippable - // and then manually inverting it - iconSizeScale.set_flippable(false); - iconSizeScale.set_inverted(true); - } - - this._settings.bind('icon-size-fixed', - this._builder.get_object('icon_size_fixed_checkbutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('extend-height', - this._builder.get_object('dock_size_extend_checkbutton'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('extend-height', - this._builder.get_object('dock_size_scale'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - this._settings.bind('always-center-icons', - this._builder.get_object('dock_center_icons_check'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('extend-height', - this._builder.get_object('dock_center_icons_check'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('multi-monitor', - this._builder.get_object('dock_monitor_combo'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN); - - - // Apps panel - - this._settings.bind('show-running', - this._builder.get_object('show_running_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - const applicationButtonIsolationButton = - this._builder.get_object('application_button_isolation_button'); - this._settings.bind('isolate-workspaces', - applicationButtonIsolationButton, - 'active', - Gio.SettingsBindFlags.DEFAULT); - applicationButtonIsolationButton.connect( - 'notify::sensitive', check => { - if (check.sensitive) { - [check.label] = check.label.split('\n'); - } else { - check.label += `\n${ - __('Managed by GNOME Multitasking\'s Application Switching setting.')}`; - } - }); - this._appSwitcherSettings.bind('current-workspace-only', - applicationButtonIsolationButton, - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN | - Gio.SettingsBindFlags.SYNC_CREATE); - this._settings.bind('workspace-agnostic-urgent-windows', - this._builder.get_object('application_button_urgent_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('isolate-monitors', - this._builder.get_object('application_button_monitor_isolation_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-windows-preview', - this._builder.get_object('windows_preview_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('multi-monitor', - this._builder.get_object('multi_monitor_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-favorites', - this._builder.get_object('show_favorite_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-trash', - this._builder.get_object('show_trash_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-mounts', - this._builder.get_object('show_mounts_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-mounts-only-mounted', - this._builder.get_object('show_only_mounted_devices_check'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-mounts-network', - this._builder.get_object('show_network_volumes_check'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('isolate-locations', - this._builder.get_object('isolate_locations_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - const isolateLocationsBindings = ['show_trash_switch', 'show_mounts_switch']; - const updateIsolateLocations = () => { - this._builder.get_object('isolate_locations_row').sensitive = - isolateLocationsBindings.some(s => this._builder.get_object(s).active); - }; - updateIsolateLocations(); - isolateLocationsBindings.forEach(s => this._builder.get_object(s).connect( - 'notify::active', () => updateIsolateLocations())); - this._settings.bind('dance-urgent-applications', - this._builder.get_object('wiggle_urgent_applications_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('hide-tooltip', - this._builder.get_object('hide_tooltip_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-icons-emblems', - this._builder.get_object('show_icons_emblems_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - const notificationsCounterCheck = this._builder.get_object( - 'notifications_counter_check'); - this._settings.bind('show-icons-notifications-counter', - notificationsCounterCheck, - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-icons-emblems', - notificationsCounterCheck, - 'sensitive', - Gio.SettingsBindFlags.GET); - - const applicationsOverrideCounter = - this._builder.get_object('applications_override_counter'); - this._settings.bind('application-counter-overrides-notifications', - applicationsOverrideCounter, - 'active', - Gio.SettingsBindFlags.DEFAULT); - notificationsCounterCheck.bind_property('active', - applicationsOverrideCounter, 'sensitive', - GObject.BindingFlags.SYNC_CREATE); - this._settings.connect('changed::show-icons-emblems', () => { - if (this._settings.get_boolean('show-icons-emblems')) - applicationsOverrideCounter.sensitive = notificationsCounterCheck.active; - else - applicationsOverrideCounter.sensitive = false; - }); - this._settings.bind('show-show-apps-button', - this._builder.get_object('show_applications_button_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-apps-at-top', - this._builder.get_object('application_button_first_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-show-apps-button', - this._builder.get_object('application_button_first_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('animate-show-apps', - this._builder.get_object('application_button_animation_button'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-show-apps-button', - this._builder.get_object('application_button_animation_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-apps-always-in-the-edge', - this._builder.get_object('show_apps_always_in_the_edge'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('show-show-apps-button', - this._builder.get_object('show_apps_always_in_the_edge'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('scroll-to-focused-application', - this._builder.get_object('scroll_to_icon_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - - // Behavior panel - - this._settings.bind('hot-keys', - this._builder.get_object('hot_keys_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('hot-keys', - this._builder.get_object('overlay_button'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT); - - this._builder.get_object('click_action_combo').set_active(this._settings.get_enum('click-action')); - this._builder.get_object('click_action_combo').connect('changed', widget => { - this._settings.set_enum('click-action', widget.get_active()); - }); - - this._builder.get_object('scroll_action_combo').set_active(this._settings.get_enum('scroll-action')); - this._builder.get_object('scroll_action_combo').connect('changed', widget => { - this._settings.set_enum('scroll-action', widget.get_active()); - }); - - this._builder.get_object('shift_click_action_combo').connect('changed', widget => { - this._settings.set_enum('shift-click-action', widget.get_active()); - }); - - this._builder.get_object('middle_click_action_combo').connect('changed', widget => { - this._settings.set_enum('middle-click-action', widget.get_active()); - }); - this._builder.get_object('shift_middle_click_action_combo').connect('changed', widget => { - this._settings.set_enum('shift-middle-click-action', widget.get_active()); - }); - - // Create dialog for number overlay options - this._builder.get_object('overlay_button').connect('clicked', () => { - const dialog = new Gtk.Dialog({ - title: __('Show dock and application numbers'), - transient_for: this.widget.get_root(), - use_header_bar: true, - modal: true, - }); - - // GTK+ leaves positive values for application-defined response ids. - // Use +1 for the reset action - dialog.add_button(__('Reset to defaults'), 1); - - const box = this._builder.get_object('box_overlay_shortcut'); - dialog.get_content_area().append(box); - - this._builder.get_object('overlay_switch').set_active( - this._settings.get_boolean('hotkeys-overlay')); - this._builder.get_object('show_dock_switch').set_active( - this._settings.get_boolean('hotkeys-show-dock')); - - // We need to update the shortcut 'strv' when the text is modified - this._settings.connect('changed::shortcut-text', () => setShortcut(this._settings)); - this._settings.bind('shortcut-text', - this._builder.get_object('shortcut_entry'), - 'text', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('hotkeys-overlay', - this._builder.get_object('overlay_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('hotkeys-show-dock', - this._builder.get_object('show_dock_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('shortcut-timeout', - this._builder.get_object('timeout_spinbutton'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - - dialog.connect('response', (_, id) => { - if (id === 1) { - // restore default settings for the relevant keys - const keys = ['shortcut-text', 'hotkeys-overlay', - 'hotkeys-show-dock', 'shortcut-timeout']; - keys.forEach(function (val) { - this._settings.set_value(val, this._settings.get_default_value(val)); - }, this); - } else { - // remove the settings box so it doesn't get destroyed; - dialog.get_content_area().remove(box); - dialog.destroy(); - } - }); - - dialog.present(); - }); - - // Create dialog for middle-click options - this._builder.get_object('middle_click_options_button').connect('clicked', () => { - const dialog = new Gtk.Dialog({ - title: __('Customize middle-click behavior'), - transient_for: this.widget.get_root(), - use_header_bar: true, - modal: true, - }); - - // GTK+ leaves positive values for application-defined response ids. - // Use +1 for the reset action - dialog.add_button(__('Reset to defaults'), 1); - - const box = this._builder.get_object('box_middle_click_options'); - dialog.get_content_area().append(box); - - this._builder.get_object('shift_click_action_combo').set_active( - this._settings.get_enum('shift-click-action')); - - this._builder.get_object('middle_click_action_combo').set_active( - this._settings.get_enum('middle-click-action')); - - this._builder.get_object('shift_middle_click_action_combo').set_active( - this._settings.get_enum('shift-middle-click-action')); - - this._settings.bind('shift-click-action', - this._builder.get_object('shift_click_action_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('middle-click-action', - this._builder.get_object('middle_click_action_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('shift-middle-click-action', - this._builder.get_object('shift_middle_click_action_combo'), - 'active-id', - Gio.SettingsBindFlags.DEFAULT); - - dialog.connect('response', (_, id) => { - if (id === 1) { - // restore default settings for the relevant keys - const keys = ['shift-click-action', 'middle-click-action', 'shift-middle-click-action']; - keys.forEach(function (val) { - this._settings.set_value(val, this._settings.get_default_value(val)); - }, this); - this._builder.get_object('shift_click_action_combo').set_active( - this._settings.get_enum('shift-click-action')); - this._builder.get_object('middle_click_action_combo').set_active( - this._settings.get_enum('middle-click-action')); - this._builder.get_object('shift_middle_click_action_combo').set_active( - this._settings.get_enum('shift-middle-click-action')); - } else { - // remove the settings box so it doesn't get destroyed; - dialog.get_content_area().remove(box); - dialog.destroy(); - } - }); - - dialog.present(); - }); - - // Appearance Panel - - this._settings.bind('apply-custom-theme', - this._builder.get_object('customize_theme'), - 'sensitive', - Gio.SettingsBindFlags.INVERT_BOOLEAN | Gio.SettingsBindFlags.GET); - this._settings.bind('apply-custom-theme', - this._builder.get_object('builtin_theme_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('custom-theme-shrink', - this._builder.get_object('shrink_dash_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - // Running indicators - this._builder.get_object('running_indicators_combo').set_active( - this._settings.get_enum('running-indicator-style') - ); - this._builder.get_object('running_indicators_combo').connect( - 'changed', - widget => { - this._settings.set_enum('running-indicator-style', widget.get_active()); - } - ); - - if (this._settings.get_enum('running-indicator-style') === RunningIndicatorStyle.DEFAULT) - this._builder.get_object('running_indicators_advance_settings_button').set_sensitive(false); - - this._settings.connect('changed::running-indicator-style', () => { - if (this._settings.get_enum('running-indicator-style') === RunningIndicatorStyle.DEFAULT) - this._builder.get_object('running_indicators_advance_settings_button').set_sensitive(false); - else - this._builder.get_object('running_indicators_advance_settings_button').set_sensitive(true); - }); - - // Create dialog for running indicators advanced settings - this._builder.get_object('running_indicators_advance_settings_button').connect('clicked', () => { - const dialog = new Gtk.Dialog({ - title: __('Customize running indicators'), - transient_for: this.widget.get_root(), - use_header_bar: true, - modal: true, - }); - - const box = this._builder.get_object('running_dots_advance_settings_box'); - dialog.get_content_area().append(box); - - this._settings.bind('running-indicator-dominant-color', - this._builder.get_object('dominant_color_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('custom-theme-customize-running-dots', - this._builder.get_object('dot_style_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('custom-theme-customize-running-dots', - this._builder.get_object('dot_style_settings_box'), - 'sensitive', Gio.SettingsBindFlags.DEFAULT); - - const rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('custom-theme-running-dots-color')); - this._builder.get_object('dot_color_colorbutton').set_rgba(rgba); - - this._builder.get_object('dot_color_colorbutton').connect('notify::rgba', button => { - const css = button.rgba.to_string(); - - this._settings.set_string('custom-theme-running-dots-color', css); - }); - - rgba.parse(this._settings.get_string('custom-theme-running-dots-border-color')); - this._builder.get_object('dot_border_color_colorbutton').set_rgba(rgba); - - this._builder.get_object('dot_border_color_colorbutton').connect('notify::rgba', button => { - const css = button.rgba.to_string(); - - this._settings.set_string('custom-theme-running-dots-border-color', css); - }); - - this._settings.bind('custom-theme-running-dots-border-width', - this._builder.get_object('dot_border_width_spin_button'), - 'value', - Gio.SettingsBindFlags.DEFAULT); - - - dialog.connect('response', () => { - // remove the settings box so it doesn't get destroyed; - dialog.get_content_area().remove(box); - dialog.destroy(); - }); - - dialog.present(); - }); - - this._settings.bind('custom-background-color', - this._builder.get_object('custom_background_color_switch'), - 'active', Gio.SettingsBindFlags.DEFAULT); - this._settings.bind('custom-background-color', - this._builder.get_object('custom_background_color'), - 'sensitive', Gio.SettingsBindFlags.DEFAULT); - - const rgba = new Gdk.RGBA(); - rgba.parse(this._settings.get_string('background-color')); - this._builder.get_object('custom_background_color').set_rgba(rgba); - - this._builder.get_object('custom_background_color').connect('notify::rgba', button => { - const css = button.rgba.to_string(); - - this._settings.set_string('background-color', css); - }); - - // Opacity - this._builder.get_object('customize_opacity_combo').set_active_id( - this._settings.get_enum('transparency-mode').toString() - ); - this._builder.get_object('customize_opacity_combo').connect( - 'changed', - widget => { - this._settings.set_enum('transparency-mode', parseInt(widget.get_active_id())); - } - ); - - const customOpacityScale = this._builder.get_object('custom_opacity_scale'); - customOpacityScale.set_value(this._settings.get_double('background-opacity')); - customOpacityScale.set_format_value_func((_, value) => { - return `${Math.round(value * 100)}%`; - }); - - if (this._settings.get_enum('transparency-mode') !== TransparencyMode.FIXED) - this._builder.get_object('custom_opacity_scale').set_sensitive(false); - - this._settings.connect('changed::transparency-mode', () => { - if (this._settings.get_enum('transparency-mode') !== TransparencyMode.FIXED) - this._builder.get_object('custom_opacity_scale').set_sensitive(false); - else - this._builder.get_object('custom_opacity_scale').set_sensitive(true); - }); - - if (this._settings.get_enum('transparency-mode') !== TransparencyMode.DYNAMIC) - this._builder.get_object('dynamic_opacity_button').set_sensitive(false); - - - this._settings.connect('changed::transparency-mode', () => { - if (this._settings.get_enum('transparency-mode') !== TransparencyMode.DYNAMIC) - this._builder.get_object('dynamic_opacity_button').set_sensitive(false); - - else - this._builder.get_object('dynamic_opacity_button').set_sensitive(true); - }); - - // Create dialog for transparency advanced settings - this._builder.get_object('dynamic_opacity_button').connect('clicked', () => { - const dialog = new Gtk.Dialog({ - title: __('Customize opacity'), - transient_for: this.widget.get_root(), - use_header_bar: true, - modal: true, - }); - - const box = this._builder.get_object('advanced_transparency_dialog'); - dialog.get_content_area().append(box); - - this._settings.bind( - 'customize-alphas', - this._builder.get_object('customize_alphas_switch'), - 'active', - Gio.SettingsBindFlags.DEFAULT - ); - this._settings.bind( - 'customize-alphas', - this._builder.get_object('min_alpha_scale'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - this._settings.bind( - 'customize-alphas', - this._builder.get_object('max_alpha_scale'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - - const minAlphaScale = this._builder.get_object('min_alpha_scale'); - const maxAlphaScale = this._builder.get_object('max_alpha_scale'); - minAlphaScale.set_value( - this._settings.get_double('min-alpha') - ); - minAlphaScale.set_format_value_func((_, value) => { - return `${Math.round(value * 100)} %`; - }); - maxAlphaScale.set_format_value_func((_, value) => { - return `${Math.round(value * 100)} %`; - }); - - maxAlphaScale.set_value( - this._settings.get_double('max-alpha') - ); - - dialog.connect('response', () => { - // remove the settings box so it doesn't get destroyed; - dialog.get_content_area().remove(box); - dialog.destroy(); - }); - - dialog.present(); - }); - - - this._settings.bind('unity-backlit-items', - this._builder.get_object('unity_backlit_items_switch'), - 'active', Gio.SettingsBindFlags.DEFAULT - ); - this._settings.bind('apply-glossy-effect', - this._builder.get_object('apply_gloss_effect_checkbutton'), - 'active', Gio.SettingsBindFlags.DEFAULT - ); - this._settings.bind('unity-backlit-items', - this._builder.get_object('apply_gloss_effect_checkbutton'), - 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - - this._settings.bind('force-straight-corner', - this._builder.get_object('force_straight_corner_switch'), - 'active', Gio.SettingsBindFlags.DEFAULT); - - this._settings.bind('disable-overview-on-startup', - this._builder.get_object('show_overview_on_startup_switch'), - 'active', Gio.SettingsBindFlags.INVERT_BOOLEAN); - - // About Panel - - this._builder.get_object('extension_version').set_label( - `${this._extensionPreferences.metadata.version}`); - } -}); - -export default class DockPreferences extends ExtensionPreferences { - getPreferencesWidget() { - const settings = new DockSettings(this); - const {widget} = settings; - return widget; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/schemas/gschemas.compiled deleted file mode 100755 index 12e460c3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml deleted file mode 100755 index 800105b5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml +++ /dev/null @@ -1,648 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'BOTTOM' - Dock position - Dock is shown on the Left, Right, Top or Bottom side of the screen. - - - 0.2 - Animation time - Sets the time duration of the autohide effect. - - - 0.25 - Show delay - Sets the delay after the mouse reaches the screen border before showing the dock. - - - 0.20 - Show delay - Sets the delay after the mouse left the dock before hiding it. - - - false - Do not show overview on startup - Whether to show or not the overview during startup animation. - - - false - Set a custom dash background background color - Sets the color for the dash background. - - - "#ffffff" - Dash background color. - Customize the background color of the dash. - - - 'DEFAULT' - Transparency mode for the dock - FIXED: constant transparency. DYNAMIC: dock takes the opaque style only when windows are close to it. - - - 'DEFAULT' - ... - DEFAULT: .... DOTS: .... - - - false - Use application icon dominant color for the indicator color - - - - false - Manually set the min and max opacity - For the dynamic mode, the min/max opacity values will be given by 'min-alpha' and 'max-alpha'. - - - 0.2 - Opacity of the dash background when free-floating - Sets the opacity of the dash background when no windows are close. - - - 0.8 - Opacity of the dash background when windows are close. - Sets the opacity of the dash background when windows are close. - - - 0.8 - Opacity of the dash background - Sets the opacity of the dash background when in autohide mode. - - - false - Dock not shown on desktop - Enable or disable manualhide mode - - - true - Dock dodges windows - Enable or disable intellihide mode - - - 'FOCUS_APPLICATION_WINDOWS' - Define which windows are considered for intellihide. - - - - true - Dock shown on mouse over - Enable or disable autohide mode - - - true - Require pressure to show dash - Enable or disable requiring pressure to show the dash - - - 100 - Pressure threshold - Sets how much pressure is needed to show the dash. - - - false - Enable autohide in fullscreen mode. - Enable autohide in fullscreen mode. - - - true - Show dock for urgent notifications. - Show dock when urgent notifications are received. - - - false - Dock always visible - Dock is always visible - - - true - Switch workspace by scrolling over the dock - Add the possibility to switch workspace by mouse scrolling over the dock. - - - 48 - Maximum dash icon size - Set the allowed maximum dash icon size. Allowed range: 16..64. - - - 0 - Preview size scale - Set the allowed maximum dash preview size scale. Allowed range: 0,00..1,00. - - - false - Fixed icon size - Keep the icon size fixed by scrolling the dock. - - - false - Apply custom theme - Apply customization to the dash appearance - - - false - TODO - TODO - - - false - Customize the style of the running application indicators. - Customize the style of the running application indicators. - - - "#ffffff" - Running application indicators color - Customize the color of the running application indicators. - - - "#ffffff" - Running application indicators border color. - Customize the border color of the running application indicators. - - - 0 - Running application indicators border width. - Customize the border width of the running application indicators. - - - true - Show running apps - Show or hide running applications icons in the dash - - - false - Provide workspace isolation - Dash shows only windows from the current workspace, this is applied only if gnome-shell 'current-workspace-only' app-switcher settings is disabled - - - true - Show urgent windows on each workspace - Show or hide urgent windows on each workspace in the dash - - - false - Provide monitor isolation - Dash shows only windows from the monitor - - - true - Scroll to focused application - Ensure that the focused application icon is always visible in the dash - - - true - Show preview of the open windows - Replace open windows list with windows previews - - - false - Open windows preview by default - Window previews will show windows by default, rather than hide them behind a drop dowm menu. - - - true - Show favorites apps - Show or hide favorite applications icons in the dash - - - true - Show trash can - Show or hide the trash can icon in the dash - - - true - Show mounted volumes and devices - Show or hide mounted volume and device icons in the dash - - - true - Only show mounted volumes and devices - Show or hide unmounted volume and device icons in the dash - - - false - Show network mounted volumes - Show or hide network volumes in the dash - - - true - Isolate volumes, devices and trash windows - Consider volume, devices and trash as different application windows and not part of the file manager - - - true - Wiggle urgent applications - Wiggle urgent application icons in the dash - - - true - Show applications button - Show applications button in the dash - - - false - Show application button on the left - Show application button on the left of the dash - - - true - Show application button on the edge when using centered panel mode - - - true - Animate Show Applications from the desktop - Animate Show Applications from the desktop - - - true - Basic compatibility with bolt extensions - Make the extension work properly when bolt extensions is enabled - - - 0.90 - Dock max height/width (fraction of available space) - - - false - Extend the dock container to all the available height/width - - - false - Center icons when dock container is extended to all the available size - - - -2 - DEPRECATED: Monitor on which putting the dock (by index) - Set on which monitor to put the dock, use -1 for the primary one. Use -2 refer to the 'preferred-monitor-by-connector' setting instead (this is the preferred value). - - - "primary" - Monitor on which putting the dock (by connector) - Set on which monitor to put the dock, for example 'DisplayPort-0'. Use 'primary' for primary one. This setting is only used if 'preferred-monitor' is -2. - - - false - Enable multi-monitor docks - Show a dock on every monitor - - - true - Minimize on shift+click - - - true - Activate only one window - - - 'cycle-windows' - Action when clicking on a running app - Set the action that is executed when clicking on the icon of a running application - - - 'do-nothing' - Action when scrolling app - Set the action that is executed when scrolling on the application icon - - - 'minimize' - Action when shift+clicking on a running app - Set the action that is executed when shift+clicking on the icon of a running application - - - 'launch' - Action when clicking on a running app - Set the action that is executed when middle-clicking on the icon of a running application - - - 'launch' - Action when clicking on a running app - Set the action that is executed when shift+middle-clicking on the icon of a running application - - - true - Super Hot-Keys - Launch and switch between dash items using Super+(0-9) - - - true - Show the dock when using the hotkeys - The dock will be quickly shown so that the number-overlay is visible and app activation is easier - - - "<Super>q" - Keybinding to show the dock and the number overlay. - Behavior depends on hotkeys-show-dock and hotkeys-overlay. - - - q']]]> - Keybinding to show the dock and the number overlay. - Behavior depends on hotkeys-show-dock and hotkeys-overlay. - - - 2 - Timeout to hide the dock - Sets the time duration before the dock is hidden again. - - - true - Show the dock when using the hotkeys - The dock will be quickly shown so that the number-overlay is visible and app activation is easier - - - 1']]]> - Keybinding to launch 1st dash app - - Keybinding to launch 1st app. - - - - 2']]]> - Keybinding to launch 2nd dash app - - Keybinding to launch 2nd app. - - - - 3']]]> - Keybinding to launch 3rd dash app - - Keybinding to launch 3rd app. - - - - 4']]]> - Keybinding to launch 4th dash app - - Keybinding to launch 4th app. - - - - 5']]]> - Keybinding to launch 5th dash app - - Keybinding to launch 5th app. - - - - 6']]]> - Keybinding to launch 6th dash app - - Keybinding to launch 6th app. - - - - 7']]]> - Keybinding to launch 7th dash app - - Keybinding to launch 7th app. - - - - 8']]]> - Keybinding to launch 8th dash app - - Keybinding to launch 8th app. - - - - 9']]]> - Keybinding to launch 9th dash app - - Keybinding to launch 9th app. - - - - 0']]]> - Keybinding to launch 10th dash app - - Keybinding to launch 10th app. - - - - 1']]]> - Keybinding to trigger 1st dash app with shift behavior - - Keybinding to trigger 1st app with shift behavior. - - - - 2']]]> - Keybinding to trigger 2nd dash app with shift behavior - - Keybinding to trigger 2nd app with shift behavior. - - - - 3']]]> - Keybinding to trigger 3rd dash app with shift behavior - - Keybinding to trigger 3rd app with shift behavior. - - - - 4']]]> - Keybinding to trigger 4th dash app with shift behavior - - Keybinding to trigger 4th app with shift behavior. - - - - 5']]]> - Keybinding to trigger 5th dash app with shift behavior - - Keybinding to trigger 5th app with shift behavior. - - - - 6']]]> - Keybinding to trigger 6th dash app with shift behavior - - Keybinding to trigger 6th app with shift behavior. - - - - 7']]]> - Keybinding to trigger 7th dash app with shift behavior - - Keybinding to trigger 7th app with shift behavior. - - - - 8']]]> - Keybinding to trigger 8th dash app with shift behavior - - Keybinding to trigger 8th app with shift behavior. - - - - 9']]]> - Keybinding to trigger 9th dash app with shift behavior - - Keybinding to trigger 9th app with shift behavior. - - - - 0']]]> - Keybinding to trigger 10th dash app with shift behavior - - Keybinding to trigger 10th app with shift behavior. - - - - 1']]]> - Keybinding to trigger 1st dash app - - Keybinding to either show or launch the 1st application in the dash. - - - - 2']]]> - Keybinding to trigger 2nd dash app - - Keybinding to either show or launch the 2nd application in the dash. - - - - 3']]]> - Keybinding to trigger 3rd dash app - - Keybinding to either show or launch the 3rd application in the dash. - - - - 4']]]> - Keybinding to trigger 4th dash app - - Keybinding to either show or launch the 4th application in the dash. - - - - 5']]]> - Keybinding to trigger 5th dash app - - Keybinding to either show or launch the 5th application in the dash. - - - - 6']]]> - Keybinding to trigger 6th dash app - - Keybinding to either show or launch the 6th application in the dash. - - - - 7']]]> - Keybinding to trigger 7th dash app - - Keybinding to either show or launch the 7th application in the dash. - - - - 8']]]> - Keybinding to trigger 8th dash app - - Keybinding to either show or launch the 8th application in the dash. - - - - 9']]]> - Keybinding to trigger 9th dash app - - Keybinding to either show or launch the 9th application in the dash. - - - - 0']]]> - Keybinding to trigger 10th dash app - - Keybinding to either show or launch the 10th application in the dash. - - - - false - Force straight corners in dash - Make the borders in the dash non rounded - - - false - Enable unity7 like glossy backlit items - Emulate the unity7 backlit glossy items behaviour - - - true - Enable glossy effect - Toggle the glossy effect of the unity7 backlit feature. - - - false - Hide application tooltip - Hide tooltip when hovering application in the dash. - - - true - Show application icons emblems - Show application icons emblems such as notification counters an progress bars. - - - true - Show the number of unread notifications in icons - Show application icons emblems such as notification - - - true - Wether the application-provioded counter via Unity API should override the notifications or be summed to it - If an application provides a counter through the Unity API, then such value will be used. Otherwise the counter will be summed with the unread notification numbers (if enabled) - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/stylesheet.css.bak b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/stylesheet.css.bak deleted file mode 100755 index 2e723995..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/stylesheet.css.bak +++ /dev/null @@ -1,1312 +0,0 @@ -.dash-item-container .overview-tile .overview-icon, -.dash-item-container .show-apps .overview-icon { - background-color: rgba(255, 255, 255, 0); } - -.dash-item-container .overview-tile:hover .overview-icon, -.dash-item-container .overview-tile.focused .overview-icon, -.dash-item-container .show-apps:hover .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - -.dash-item-container .overview-tile .app-grid-running-dot { - margin-bottom: 8px; } - -#dashtodockContainer.bottom #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.bottom #dash .dash-background { - margin: 0; - margin-bottom: 4px; - padding: 0; - border-radius: 24px; - spacing: 6px; } - #dashtodockContainer.bottom #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 4px; - width: 1px; - height: 0; - margin-bottom: 4px; } - #dashtodockContainer.bottom #dash #dashtodockDashContainer { - padding: 10px; - padding-bottom: 0; - padding-top: 0; } - #dashtodockContainer.bottom #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.bottom #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.bottom #dash .dash-item-container:ltr:first-child, #dashtodockContainer.bottom #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.bottom #dash .dash-item-container:ltr:last-child, #dashtodockContainer.bottom #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.bottom #dash .dash-item-container .app-well-app, - #dashtodockContainer.bottom #dash .dash-item-container .show-apps, - #dashtodockContainer.bottom #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-bottom: 14px; - padding-top: 10px; } - #dashtodockContainer.bottom #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.bottom #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.bottom #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.bottom #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.bottom #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.bottom #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.bottom #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.bottom #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.bottom #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.bottom #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.bottom #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.bottom #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.bottom #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.bottom #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.bottom #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.bottom #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.bottom.fixed #dash .dash-background { - margin-top: 4px; } - -#dashtodockContainer.bottom.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.bottom.fixed #dash .dash-item-container .show-apps { - padding-top: 14px; } - -.dash-label.bottom { - margin-bottom: 10px; - -x-offset: 0; - -y-offset: 0; } - -#dashtodockContainer.bottom.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.bottom.shrink #dash .dash-background { - margin: 0; - margin-bottom: 4px; - padding: 0; - border-radius: 18px; - spacing: 2px; } - #dashtodockContainer.bottom.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 1px; - width: 1px; - height: 0; - margin-bottom: 4px; } - #dashtodockContainer.bottom.shrink #dash #dashtodockDashContainer { - padding: 3px; - padding-bottom: 0; - padding-top: 0; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container:ltr:first-child, #dashtodockContainer.bottom.shrink #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container:ltr:last-child, #dashtodockContainer.bottom.shrink #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-bottom: 7px; - padding-top: 3px; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.bottom.shrink #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.bottom.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.bottom.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.bottom.shrink.fixed #dash .dash-background { - margin-top: 1px; } - -#dashtodockContainer.bottom.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.bottom.shrink.fixed #dash .dash-item-container .show-apps { - padding-top: 4px; } - -.dash-label.bottom.shrink { - margin-bottom: 3px; - -x-offset: 0; - -y-offset: 0; } - -#dashtodockContainer.bottom.extended #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.bottom.extended #dash .dash-background { - margin: 0; - margin-bottom: 0; - padding: 0; - border-radius: 0; - spacing: 6px; } - #dashtodockContainer.bottom.extended #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 4px; - width: 1px; - height: 0; - margin-bottom: 0; } - #dashtodockContainer.bottom.extended #dash #dashtodockDashContainer { - padding: 0; - padding-bottom: 0; - padding-top: 0; } - #dashtodockContainer.bottom.extended #dash #dashtodockDashContainer > :first-child .show-apps { - padding-left: 8px; } - #dashtodockContainer.bottom.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-left: 8px; } - #dashtodockContainer.bottom.extended #dash #dashtodockDashContainer > :last-child .show-apps { - padding-right: 8px; } - #dashtodockContainer.bottom.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-right: 8px; } - #dashtodockContainer.bottom.extended #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.bottom.extended #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.bottom.extended #dash .dash-item-container:ltr:first-child, #dashtodockContainer.bottom.extended #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.bottom.extended #dash .dash-item-container:ltr:last-child, #dashtodockContainer.bottom.extended #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app, - #dashtodockContainer.bottom.extended #dash .dash-item-container .show-apps, - #dashtodockContainer.bottom.extended #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-bottom: 10px; - padding-top: 10px; } - #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.bottom.extended #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.bottom.extended #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.bottom.extended #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.bottom.extended.fixed #dash .dash-background { - margin-top: 0; } - -#dashtodockContainer.bottom.extended.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.bottom.extended.fixed #dash .dash-item-container .show-apps { - padding-top: 10px; } - -.dash-label.bottom { - margin-bottom: 10px; - -x-offset: 0; - -y-offset: 0; } - -#dashtodockContainer.bottom.extended.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-background { - margin: 0; - margin-bottom: 0; - padding: 0; - border-radius: 0; - spacing: 2px; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 1px; - width: 1px; - height: 0; - margin-bottom: 0; } - #dashtodockContainer.bottom.extended.shrink #dash #dashtodockDashContainer { - padding: 0; - padding-bottom: 0; - padding-top: 0; } - #dashtodockContainer.bottom.extended.shrink #dash #dashtodockDashContainer > :first-child .show-apps { - padding-left: 6px; } - #dashtodockContainer.bottom.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-left: 6px; } - #dashtodockContainer.bottom.extended.shrink #dash #dashtodockDashContainer > :last-child .show-apps { - padding-right: 6px; } - #dashtodockContainer.bottom.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-right: 6px; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container:ltr:first-child, #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container:ltr:last-child, #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-bottom: 3px; - padding-top: 3px; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.bottom.extended.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.bottom.extended.shrink.fixed #dash .dash-background { - margin-top: 0; } - -#dashtodockContainer.bottom.extended.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.bottom.extended.shrink.fixed #dash .dash-item-container .show-apps { - padding-top: 3px; } - -.dash-label.bottom.shrink { - margin-bottom: 3px; - -x-offset: 0; - -y-offset: 0; } - -.dashtodock-app-well-preview-menu-item.bottom { - padding: 0.5em 0.5em; } - .dashtodock-app-well-preview-menu-item.bottom:ltr:first-child, .dashtodock-app-well-preview-menu-item.bottom:rtl:last-child { - padding-left: 1em; } - .dashtodock-app-well-preview-menu-item.bottom:ltr:last-child, .dashtodock-app-well-preview-menu-item.bottom:rtl:first-child { - padding-right: 1em; } - -#dashtodockContainer.top #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.top #dash .dash-background { - margin: 0; - margin-top: 4px; - padding: 0; - border-radius: 24px; - spacing: 6px; } - #dashtodockContainer.top #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 4px; - width: 1px; - height: 0; - margin-top: 4px; } - #dashtodockContainer.top #dash #dashtodockDashContainer { - padding: 10px; - padding-top: 0; - padding-bottom: 0; } - #dashtodockContainer.top #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.top #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.top #dash .dash-item-container:ltr:first-child, #dashtodockContainer.top #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.top #dash .dash-item-container:ltr:last-child, #dashtodockContainer.top #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.top #dash .dash-item-container .app-well-app, - #dashtodockContainer.top #dash .dash-item-container .show-apps, - #dashtodockContainer.top #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-top: 14px; - padding-bottom: 10px; } - #dashtodockContainer.top #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.top #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.top #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.top #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.top #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.top #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.top #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.top #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.top #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.top #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.top #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.top #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.top #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.top #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.top #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.top #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.top.fixed #dash .dash-background { - margin-bottom: 4px; } - -#dashtodockContainer.top.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.top.fixed #dash .dash-item-container .show-apps { - padding-bottom: 14px; } - -.dash-label.top { - margin-top: 10px; - -x-offset: 0; - -y-offset: 0; } - -#dashtodockContainer.top.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.top.shrink #dash .dash-background { - margin: 0; - margin-top: 4px; - padding: 0; - border-radius: 18px; - spacing: 2px; } - #dashtodockContainer.top.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 1px; - width: 1px; - height: 0; - margin-top: 4px; } - #dashtodockContainer.top.shrink #dash #dashtodockDashContainer { - padding: 3px; - padding-top: 0; - padding-bottom: 0; } - #dashtodockContainer.top.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.top.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.top.shrink #dash .dash-item-container:ltr:first-child, #dashtodockContainer.top.shrink #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.top.shrink #dash .dash-item-container:ltr:last-child, #dashtodockContainer.top.shrink #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.top.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.top.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-top: 7px; - padding-bottom: 3px; } - #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.top.shrink #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.top.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.top.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.top.shrink.fixed #dash .dash-background { - margin-bottom: 1px; } - -#dashtodockContainer.top.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.top.shrink.fixed #dash .dash-item-container .show-apps { - padding-bottom: 4px; } - -.dash-label.top.shrink { - margin-top: 3px; - -x-offset: 0; - -y-offset: 0; } - -#dashtodockContainer.top.extended #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.top.extended #dash .dash-background { - margin: 0; - margin-top: 0; - padding: 0; - border-radius: 0; - spacing: 6px; } - #dashtodockContainer.top.extended #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 4px; - width: 1px; - height: 0; - margin-top: 0; } - #dashtodockContainer.top.extended #dash #dashtodockDashContainer { - padding: 0; - padding-top: 0; - padding-bottom: 0; } - #dashtodockContainer.top.extended #dash #dashtodockDashContainer > :first-child .show-apps { - padding-left: 8px; } - #dashtodockContainer.top.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-left: 8px; } - #dashtodockContainer.top.extended #dash #dashtodockDashContainer > :last-child .show-apps { - padding-right: 8px; } - #dashtodockContainer.top.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-right: 8px; } - #dashtodockContainer.top.extended #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.top.extended #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.top.extended #dash .dash-item-container:ltr:first-child, #dashtodockContainer.top.extended #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.top.extended #dash .dash-item-container:ltr:last-child, #dashtodockContainer.top.extended #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app, - #dashtodockContainer.top.extended #dash .dash-item-container .show-apps, - #dashtodockContainer.top.extended #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-top: 10px; - padding-bottom: 10px; } - #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.top.extended #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.top.extended #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.top.extended #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.top.extended #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.top.extended #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.top.extended #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.top.extended #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.top.extended #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.top.extended #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.top.extended #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.top.extended.fixed #dash .dash-background { - margin-bottom: 0; } - -#dashtodockContainer.top.extended.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.top.extended.fixed #dash .dash-item-container .show-apps { - padding-bottom: 10px; } - -.dash-label.top { - margin-top: 10px; - -x-offset: 0; - -y-offset: 0; } - -#dashtodockContainer.top.extended.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.top.extended.shrink #dash .dash-background { - margin: 0; - margin-top: 0; - padding: 0; - border-radius: 0; - spacing: 2px; } - #dashtodockContainer.top.extended.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - margin: 0 1px; - width: 1px; - height: 0; - margin-top: 0; } - #dashtodockContainer.top.extended.shrink #dash #dashtodockDashContainer { - padding: 0; - padding-top: 0; - padding-bottom: 0; } - #dashtodockContainer.top.extended.shrink #dash #dashtodockDashContainer > :first-child .show-apps { - padding-left: 6px; } - #dashtodockContainer.top.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-left: 6px; } - #dashtodockContainer.top.extended.shrink #dash #dashtodockDashContainer > :last-child .show-apps { - padding-right: 6px; } - #dashtodockContainer.top.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-right: 6px; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 0 2px; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container:ltr:first-child, #dashtodockContainer.top.extended.shrink #dash .dash-item-container:rtl:last-child { - margin-left: 0; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container:ltr:last-child, #dashtodockContainer.top.extended.shrink #dash .dash-item-container:rtl:first-child { - margin-right: 0; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-top: 3px; - padding-bottom: 3px; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app:ltr:first-child, #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app:rtl:last-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .show-apps:ltr:first-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .show-apps:rtl:last-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .overview-tile:ltr:first-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .overview-tile:rtl:last-child { - padding-left: 0; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app:ltr:last-child, #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app:rtl:first-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .show-apps:ltr:last-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .show-apps:rtl:first-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .overview-tile:ltr:last-child, - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .overview-tile:rtl:first-child { - padding-right: 0; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.top.extended.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.top.extended.shrink.fixed #dash .dash-background { - margin-bottom: 0; } - -#dashtodockContainer.top.extended.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.top.extended.shrink.fixed #dash .dash-item-container .show-apps { - padding-bottom: 3px; } - -.dash-label.top.shrink { - margin-top: 3px; - -x-offset: 0; - -y-offset: 0; } - -.dashtodock-app-well-preview-menu-item.top { - padding: 0.5em 0.5em; } - .dashtodock-app-well-preview-menu-item.top:ltr:first-child, .dashtodock-app-well-preview-menu-item.top:rtl:last-child { - padding-left: 1em; } - .dashtodock-app-well-preview-menu-item.top:ltr:last-child, .dashtodock-app-well-preview-menu-item.top:rtl:first-child { - padding-right: 1em; } - -#dashtodockContainer.left #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.left #dash .dash-background { - margin: 0; - margin-left: 4px; - padding: 0; - border-radius: 24px; - spacing: 6px; } - #dashtodockContainer.left #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 4px 0; - margin-left: 4px; } - #dashtodockContainer.left #dash #dashtodockDashContainer { - padding: 10px; - padding-left: 0; - padding-right: 0; } - #dashtodockContainer.left #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.left #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.left #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.left #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.left #dash .dash-item-container .app-well-app, - #dashtodockContainer.left #dash .dash-item-container .show-apps, - #dashtodockContainer.left #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-left: 14px; - padding-right: 10px; } - #dashtodockContainer.left #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.left #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.left #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.left #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.left #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.left #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.left #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.left #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.left #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.left #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.left.fixed #dash .dash-background { - margin-right: 4px; } - -#dashtodockContainer.left.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.left.fixed #dash .dash-item-container .show-apps { - padding-right: 14px; } - -.dash-label.left { - margin: 0; - -x-offset: 10px; - -y-offset: 0; } - -#dashtodockContainer.left.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.left.shrink #dash .dash-background { - margin: 0; - margin-left: 4px; - padding: 0; - border-radius: 18px; - spacing: 2px; } - #dashtodockContainer.left.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 1px 0; - margin-left: 4px; } - #dashtodockContainer.left.shrink #dash #dashtodockDashContainer { - padding: 3px; - padding-left: 0; - padding-right: 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.left.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.left.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-left: 7px; - padding-right: 3px; } - #dashtodockContainer.left.shrink #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.left.shrink #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.left.shrink #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.left.shrink #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.left.shrink #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.left.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.left.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.left.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.left.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.left.shrink.fixed #dash .dash-background { - margin-right: 1px; } - -#dashtodockContainer.left.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.left.shrink.fixed #dash .dash-item-container .show-apps { - padding-right: 4px; } - -.dash-label.left.shrink { - margin: 0; - -x-offset: 3px; - -y-offset: 0; } - -#dashtodockContainer.left.extended #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.left.extended #dash .dash-background { - margin: 0; - margin-left: 0; - padding: 0; - border-radius: 0; - spacing: 6px; } - #dashtodockContainer.left.extended #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 4px 0; - margin-left: 0; } - #dashtodockContainer.left.extended #dash #dashtodockDashContainer { - padding: 0; - padding-left: 0; - padding-right: 0; } - #dashtodockContainer.left.extended #dash #dashtodockDashContainer > :first-child .show-apps { - padding-top: 8px; } - #dashtodockContainer.left.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-top: 8px; } - #dashtodockContainer.left.extended #dash #dashtodockDashContainer > :last-child .show-apps { - padding-bottom: 8px; } - #dashtodockContainer.left.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-bottom: 8px; } - #dashtodockContainer.left.extended #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.left.extended #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.left.extended #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.left.extended #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.left.extended #dash .dash-item-container .app-well-app, - #dashtodockContainer.left.extended #dash .dash-item-container .show-apps, - #dashtodockContainer.left.extended #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-left: 10px; - padding-right: 10px; } - #dashtodockContainer.left.extended #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.left.extended #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.left.extended #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.left.extended #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.left.extended #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.left.extended #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.left.extended #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.left.extended #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.left.extended #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.left.extended #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.left.extended.fixed #dash .dash-background { - margin-right: 0; } - -#dashtodockContainer.left.extended.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.left.extended.fixed #dash .dash-item-container .show-apps { - padding-right: 10px; } - -.dash-label.left { - margin: 0; - -x-offset: 10px; - -y-offset: 0; } - -#dashtodockContainer.left.extended.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.left.extended.shrink #dash .dash-background { - margin: 0; - margin-left: 0; - padding: 0; - border-radius: 0; - spacing: 2px; } - #dashtodockContainer.left.extended.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 1px 0; - margin-left: 0; } - #dashtodockContainer.left.extended.shrink #dash #dashtodockDashContainer { - padding: 0; - padding-left: 0; - padding-right: 0; } - #dashtodockContainer.left.extended.shrink #dash #dashtodockDashContainer > :first-child .show-apps { - padding-top: 6px; } - #dashtodockContainer.left.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-top: 6px; } - #dashtodockContainer.left.extended.shrink #dash #dashtodockDashContainer > :last-child .show-apps { - padding-bottom: 6px; } - #dashtodockContainer.left.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-bottom: 6px; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-left: 3px; - padding-right: 3px; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.left.extended.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.left.extended.shrink.fixed #dash .dash-background { - margin-right: 0; } - -#dashtodockContainer.left.extended.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.left.extended.shrink.fixed #dash .dash-item-container .show-apps { - padding-right: 3px; } - -.dash-label.left.shrink { - margin: 0; - -x-offset: 3px; - -y-offset: 0; } - -.dashtodock-app-well-preview-menu-item.left { - padding: 0.5em 0.5em; } - .dashtodock-app-well-preview-menu-item.left:first-child { - padding-top: 1em; } - .dashtodock-app-well-preview-menu-item.left:last-child { - padding-bottom: 1em; } - -#dashtodockContainer.right #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.right #dash .dash-background { - margin: 0; - margin-right: 4px; - padding: 0; - border-radius: 24px; - spacing: 6px; } - #dashtodockContainer.right #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 4px 0; - margin-right: 4px; } - #dashtodockContainer.right #dash #dashtodockDashContainer { - padding: 10px; - padding-right: 0; - padding-left: 0; } - #dashtodockContainer.right #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.right #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.right #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.right #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.right #dash .dash-item-container .app-well-app, - #dashtodockContainer.right #dash .dash-item-container .show-apps, - #dashtodockContainer.right #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-right: 14px; - padding-left: 10px; } - #dashtodockContainer.right #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.right #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.right #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.right #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.right #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.right #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.right #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.right #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.right #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.right #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.right.fixed #dash .dash-background { - margin-left: 4px; } - -#dashtodockContainer.right.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.right.fixed #dash .dash-item-container .show-apps { - padding-left: 14px; } - -.dash-label.right { - margin: 0; - -x-offset: 10px; - -y-offset: 0; } - -#dashtodockContainer.right.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.right.shrink #dash .dash-background { - margin: 0; - margin-right: 4px; - padding: 0; - border-radius: 18px; - spacing: 2px; } - #dashtodockContainer.right.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 1px 0; - margin-right: 4px; } - #dashtodockContainer.right.shrink #dash #dashtodockDashContainer { - padding: 3px; - padding-right: 0; - padding-left: 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.right.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.right.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-right: 7px; - padding-left: 3px; } - #dashtodockContainer.right.shrink #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.right.shrink #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.right.shrink #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.right.shrink #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.right.shrink #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.right.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.right.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.right.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.right.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.right.shrink.fixed #dash .dash-background { - margin-left: 1px; } - -#dashtodockContainer.right.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.right.shrink.fixed #dash .dash-item-container .show-apps { - padding-left: 4px; } - -.dash-label.right.shrink { - margin: 0; - -x-offset: 3px; - -y-offset: 0; } - -#dashtodockContainer.right.extended #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.right.extended #dash .dash-background { - margin: 0; - margin-right: 0; - padding: 0; - border-radius: 0; - spacing: 6px; } - #dashtodockContainer.right.extended #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 4px 0; - margin-right: 0; } - #dashtodockContainer.right.extended #dash #dashtodockDashContainer { - padding: 0; - padding-right: 0; - padding-left: 0; } - #dashtodockContainer.right.extended #dash #dashtodockDashContainer > :first-child .show-apps { - padding-top: 8px; } - #dashtodockContainer.right.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-top: 8px; } - #dashtodockContainer.right.extended #dash #dashtodockDashContainer > :last-child .show-apps { - padding-bottom: 8px; } - #dashtodockContainer.right.extended #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-bottom: 8px; } - #dashtodockContainer.right.extended #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.right.extended #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.right.extended #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.right.extended #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.right.extended #dash .dash-item-container .app-well-app, - #dashtodockContainer.right.extended #dash .dash-item-container .show-apps, - #dashtodockContainer.right.extended #dash .dash-item-container .overview-tile { - padding: 2px 2px; - padding-right: 10px; - padding-left: 10px; } - #dashtodockContainer.right.extended #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.right.extended #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.right.extended #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.right.extended #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.right.extended #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.right.extended #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.right.extended #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.right.extended #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.right.extended #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.right.extended #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.right.extended.fixed #dash .dash-background { - margin-left: 0; } - -#dashtodockContainer.right.extended.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.right.extended.fixed #dash .dash-item-container .show-apps { - padding-left: 10px; } - -.dash-label.right { - margin: 0; - -x-offset: 10px; - -y-offset: 0; } - -#dashtodockContainer.right.extended.shrink #dash { - margin: 0px; - padding: 0px; } - #dashtodockContainer.right.extended.shrink #dash .dash-background { - margin: 0; - margin-right: 0; - padding: 0; - border-radius: 0; - spacing: 2px; } - #dashtodockContainer.right.extended.shrink #dash .dash-separator { - background-color: rgba(255, 255, 255, 0.1); - width: 0; - height: 1px; - margin: 1px 0; - margin-right: 0; } - #dashtodockContainer.right.extended.shrink #dash #dashtodockDashContainer { - padding: 0; - padding-right: 0; - padding-left: 0; } - #dashtodockContainer.right.extended.shrink #dash #dashtodockDashContainer > :first-child .show-apps { - padding-top: 6px; } - #dashtodockContainer.right.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:first-child { - padding-top: 6px; } - #dashtodockContainer.right.extended.shrink #dash #dashtodockDashContainer > :last-child .show-apps { - padding-bottom: 6px; } - #dashtodockContainer.right.extended.shrink #dash #dashtodockDashContainer #dashtodockDashScrollview:last-child { - padding-bottom: 6px; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container { - /* Disable all margins defined upstream, we handle them here */ - margin: 2px 0; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container > * { - margin: 0; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container:first-child { - margin-top: 0; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container:last-child { - margin-bottom: 0; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .app-well-app, - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .show-apps, - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .overview-tile { - padding: 1px 1px; - padding-right: 3px; - padding-left: 3px; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .app-well-app:first-child, - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .show-apps:first-child, - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .overview-tile:first-child { - padding-top: 0; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .app-well-app:last-child, - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .show-apps:last-child, - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .overview-tile:last-child { - padding-bottom: 0; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .app-well-app.running .overview-icon { - background-image: none; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .app-well-app.focused .overview-icon { - background-color: rgba(238, 238, 238, 0.2); } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container .app-well-app .app-well-app-running-dot { - margin-bottom: 2px; } - #dashtodockContainer.right.extended.shrink #dash .dash-item-container > StButton { - transition-duration: 250; - background-size: contain; } - -#dashtodockContainer.right.extended.shrink.fixed #dash .dash-background { - margin-left: 0; } - -#dashtodockContainer.right.extended.shrink.fixed #dash .dash-item-container .app-well-app, -#dashtodockContainer.right.extended.shrink.fixed #dash .dash-item-container .show-apps { - padding-left: 3px; } - -.dash-label.right.shrink { - margin: 0; - -x-offset: 3px; - -y-offset: 0; } - -.dashtodock-app-well-preview-menu-item.right { - padding: 0.5em 0.5em; } - .dashtodock-app-well-preview-menu-item.right:first-child { - padding-top: 1em; } - .dashtodock-app-well-preview-menu-item.right:last-child { - padding-bottom: 1em; } - -#dashtodockContainer.top.shrink #dash .dash-background { - margin-top: 4px; - margin-bottom: 0; } - -#dashtodockContainer.straight-corner #dash .dash-background, -#dashtodockContainer.shrink.straight-corner #dash .dash-background { - border-radius: 0px; } - -/* Scrollview style */ -.bottom #dashtodockDashScrollview, -.top #dashtodockDashScrollview { - -st-hfade-offset: 24px; } - -.left #dashtodockDashScrollview, -.right #dashtodockDashScrollview { - -st-vfade-offset: 24px; } - -#dashtodockContainer.dashtodock #dash .dash-background { - background: #303030; } - -#dashtodockContainer.dashtodock .progress-bar { - /* Customization of the progress bar style. The possible elements - * are: - * - * -XXXXXX-YYYYYY: plain color - * -XXXXXX-YYYYYY-color-start: start color for gradient - * -XXXXXX-YYYYYY-color-end: end color for gradient - * -XXXXXX-YYYYYY-offset-start: offset for start color in gradient (0-1) - * -XXXXXX-YYYYYY-offset-end: offset for end color in gradient (0-1) - * -XXXXXX-line-width: width value for the line used for the border - * - * XXXXXX can be either - * - * progress-bar-track: the "track" over which the progress bar is shown - * progress-bar: the progress bar itself - * - * YYYYYY can be either - * - * background: for the background color - * border: for the border color - * - * plain color entries have priority over gradients, so if both are set for - * an element, the plain color will be used. - * - * Examples: - * - * -progress-bar-track-background: rgba(128, 128, 0, 0.75); - * -progress-bar-track-border: rgba(0, 0, 255, 0.25); - * - * -progress-bar-background: rgba(0, 204, 204, 1); - * -progress-bar-border: rgba(230, 230, 230, 1); - * - * Default values when these entries aren't set are equivalent to: - * -progress-bar-track-background-color-start: 64, 64, 64, 1.0 - * -progress-bar-track-background-color-end: 89, 89, 89, 1.0 - * -progress-bar-track-background-start-offset: 0.4 - * -progress-bar-track-background-end-offset: 0.9 - * -progress-bar-track-border-color-start: 128, 128, 128, 0.1 - * -progress-bar-track-border-color-end: 89, 89, 89, 0.4 - * -progress-bar-track-border-start-offset: 0.5 - * -progress-bar-track-border-end-offset: 0.9 - * -progress-bar-track-line-width: 1 - * -progress-bar-background: 204, 204, 204, 1.0 - * -progress-bar-border: 230, 230, 230, 1.0 - * -progress-bar-line-width: 1 - */ - -progress-bar-track-background: rgba(0, 0, 0, 0.45); - -progress-bar-track-border: rgba(0, 0, 0, 0.7); - -progress-bar-background: white; - -progress-bar-border: white; } - -#dashtodockContainer.top #dash .placeholder, -#dashtodockContainer.bottom #dash .placeholder { - width: 32px; - height: 1px; } - -/* - * This is applied to a dummy actor. Only the alpha value for the background and border color - * and the transition-duration are used - */ -#dashtodockContainer.dummy-opaque { - background-color: rgba(0, 0, 0, 0.8); - border-color: rgba(0, 0, 0, 0.4); - transition-duration: 300ms; } - -/* - * This is applied to a dummy actor. Only the alpha value for the background and border color - * and the transition-duration are used - */ -#dashtodockContainer.dummy-transparent { - background-color: rgba(0, 0, 0, 0.2); - border-color: rgba(0, 0, 0, 0.1); - transition-duration: 500ms; } - -#dashtodockContainer .number-overlay { - color: white; - background-color: rgba(0, 0, 0, 0.8); - text-align: center; } - -#dashtodockContainer .notification-badge { - color: white; - background-color: red; - padding: 0.2em 0.5em; - border-radius: 1em; - font-weight: bold; - text-align: center; - margin: 2px; } - -#dashtodockPreviewSeparator.popup-separator-menu-item-horizontal { - width: 1px; - height: auto; - border-right-width: 1px; - margin: 32px 0px; } - -#dashtodockContainer .metro .overview-icon { - border-radius: 0px; } - -#dashtodockContainer.bottom .metro.running2.focused, -#dashtodockContainer.top .metro.running2.focused { - background-image: url("./media/highlight_stacked_bg.svg"); - background-position: 0px 0px; - background-size: contain; } - -#dashtodockContainer.left .metro.running2.focused, -#dashtodockContainer.right .metro.running2.focused { - background-image: url("./media/highlight_stacked_bg_h.svg"); - background-position: 0px 0px; - background-size: contain; } - -#dashtodockContainer.bottom .metro.running3.focused, -#dashtodockContainer.top .metro.running3.focused { - background-image: url("./media/highlight_stacked_bg.svg"); - background-position: 0px 0px; - background-size: contain; } - -#dashtodockContainer.left .metro.running3.focused, -#dashtodockContainer.right .metro.running3.focused { - background-image: url("./media/highlight_stacked_bg_h.svg"); - background-position: 0px 0px; - background-size: contain; } - -#dashtodockContainer.bottom .metro.running4.focused, -#dashtodockContainer.top .metro.running4.focused { - background-image: url("./media/highlight_stacked_bg.svg"); - background-position: 0px 0px; - background-size: contain; } - -#dashtodockContainer.left .metro.running4.focused, -#dashtodockContainer.right .metro.running4.focused { - background-image: url("./media/highlight_stacked_bg_h.svg"); - background-position: 0px 0px; - background-size: contain; } diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/theming.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/theming.js deleted file mode 100755 index 87471a35..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/theming.js +++ /dev/null @@ -1,570 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -import { - Clutter, - GObject, - Meta, - St, -} from './dependencies/gi.js'; - -import {Main} from './dependencies/shell/ui.js'; - -import { - Docking, - Utils, -} from './imports.js'; - -const {signals: Signals} = imports; - -/* - * DEFAULT: transparency given by theme - * FIXED: constant transparency chosen by user - * DYNAMIC: apply 'transparent' style when no windows are close to the dock - * */ -const TransparencyMode = { - DEFAULT: 0, - FIXED: 1, - DYNAMIC: 3, -}; - -const Labels = Object.freeze({ - TRANSPARENCY: Symbol('transparency'), -}); - -export const PositionStyleClass = Object.freeze([ - 'top', - 'right', - 'bottom', - 'left', -]); - -/** - * Manage theme customization and custom theme support - */ -export class ThemeManager { - constructor(dock) { - this._signalsHandler = new Utils.GlobalSignalsHandler(this); - this._bindSettingsChanges(); - this._actor = dock; - this._dash = dock.dash; - - // initialize colors with generic values - this._customizedBackground = {red: 0, green: 0, blue: 0, alpha: 0}; - this._customizedBorder = {red: 0, green: 0, blue: 0, alpha: 0}; - this._transparency = new Transparency(dock); - - this._signalsHandler.add([ - // When theme changes re-obtain default background color - St.ThemeContext.get_for_stage(global.stage), - 'changed', - this.updateCustomTheme.bind(this), - ], [ - // update :overview pseudoclass - Main.overview, - 'showing', - this._onOverviewShowing.bind(this), - ], [ - Main.overview, - 'hiding', - this._onOverviewHiding.bind(this), - ]); - - this._updateCustomStyleClasses(); - - // destroy themeManager when the managed actor is destroyed (e.g. extension unload) - // in order to disconnect signals - this._signalsHandler.add(this._actor, 'destroy', () => this.destroy()); - } - - destroy() { - this.emit('destroy'); - this._transparency.destroy(); - this._destroyed = true; - } - - _onOverviewShowing() { - this._actor.add_style_pseudo_class('overview'); - } - - _onOverviewHiding() { - this._actor.remove_style_pseudo_class('overview'); - } - - _updateDashOpacity() { - const newAlpha = Docking.DockManager.settings.backgroundOpacity; - - const [backgroundColor, borderColor] = this._getDefaultColors(); - - if (!backgroundColor) - return; - - // Get the background and border alphas. We check the background alpha - // for a minimum of .001 to prevent division by 0 errors - const backgroundAlpha = Math.max(Math.round(backgroundColor.alpha / 2.55) / 100, .001); - let borderAlpha = Math.round(borderColor.alpha / 2.55) / 100; - - // The border and background alphas should remain in sync - // We also limit the borderAlpha to a maximum of 1 (full opacity) - borderAlpha = Math.min((borderAlpha / backgroundAlpha) * newAlpha, 1); - - this._customizedBackground = `rgba(${ - backgroundColor.red},${ - backgroundColor.green},${ - backgroundColor.blue},${ - newAlpha})`; - - this._customizedBorder = `rgba(${ - borderColor.red},${ - borderColor.green},${ - borderColor.blue},${ - borderAlpha})`; - } - - _getDefaultColors() { - // Prevent shell crash if the actor is not on the stage. - // It happens enabling/disabling repeatedly the extension - if (!this._dash._background.get_stage()) - return [null, null]; - - // Remove custom style - const oldStyle = this._dash._background.get_style(); - this._dash._background.set_style(null); - - const themeNode = this._dash._background.get_theme_node(); - this._dash._background.set_style(oldStyle); - - const backgroundColor = themeNode.get_background_color(); - - // Just in case the theme has different border colors .. - // We want to find the inside border-color of the dock because it is - // the side most visible to the user. We do this by finding the side - // opposite the position - const position = Utils.getPosition(); - let side = position + 2; - if (side > 3) - side = Math.abs(side - 4); - - const borderColor = themeNode.get_border_color(side); - - return [backgroundColor, borderColor]; - } - - _updateDashColor() { - // Retrieve the color. If needed we will adjust it before passing it to - // this._transparency. - let [backgroundColor] = this._getDefaultColors(); - - if (!backgroundColor) - return; - - const {settings} = Docking.DockManager; - - if (settings.customBackgroundColor) { - // When applying a custom color, we need to check the alpha value, - // if not the opacity will always be overridden by the color below. - // Note that if using 'dynamic' transparency modes, - // the opacity will be set by the opaque/transparent styles anyway. - let newAlpha = Math.round(backgroundColor.alpha / 2.55) / 100; - - ({backgroundColor} = settings); - // backgroundColor is a string like rgb(0,0,0) - const [ret, color] = Clutter.Color.from_string(backgroundColor); - if (!ret) { - logError(new Error(`${backgroundColor} is not a valid color string`)); - return; - } - - if (settings.transparencyMode === TransparencyMode.FIXED) { - newAlpha = settings.backgroundOpacity; - this._customizedBackground = - `rgba(${color.red}, ${color.green}, ${color.blue}, ${newAlpha})`; - } else { - this._customizedBackground = backgroundColor; - } - - this._customizedBorder = this._customizedBackground; - - color.alpha = newAlpha * 255; - this._transparency.setColor(color); - } else { - // backgroundColor is a Clutter.Color object - this._transparency.setColor(backgroundColor); - } - } - - _updateCustomStyleClasses() { - const {settings} = Docking.DockManager; - - if (settings.applyCustomTheme) - this._actor.add_style_class_name('dashtodock'); - else - this._actor.remove_style_class_name('dashtodock'); - - if (settings.customThemeShrink) - this._actor.add_style_class_name('shrink'); - else - this._actor.remove_style_class_name('shrink'); - - if (settings.runningIndicatorStyle !== 0) - this._actor.add_style_class_name('running-dots'); - else - this._actor.remove_style_class_name('running-dots'); - - // If not the built-in theme option is not selected - if (!settings.applyCustomTheme) { - if (settings.forceStraightCorner) - this._actor.add_style_class_name('straight-corner'); - else - this._actor.remove_style_class_name('straight-corner'); - } else { - this._actor.remove_style_class_name('straight-corner'); - } - } - - updateCustomTheme() { - if (this._destroyed) - throw new Error(`Impossible to update a destroyed ${this.constructor.name}`); - this._updateCustomStyleClasses(); - this._updateDashOpacity(); - this._updateDashColor(); - this._adjustTheme(); - this.emit('updated'); - } - - /** - * Reimported back and adapted from atomdock - */ - _adjustTheme() { - // Prevent shell crash if the actor is not on the stage. - // It happens enabling/disabling repeatedly the extension - if (!this._dash._background.get_stage()) - return; - - const {settings} = Docking.DockManager; - - // Remove prior style edits - this._dash._background.set_style(null); - this._transparency.disable(); - - // If built-in theme is enabled do nothing else - if (settings.applyCustomTheme) - return; - - let newStyle = ''; - const position = Utils.getPosition(settings); - - // obtain theme border settings - const themeNode = this._dash._background.get_theme_node(); - const borderColor = themeNode.get_border_color(St.Side.TOP); - const borderWidth = themeNode.get_border_width(St.Side.TOP); - - // We're copying border and corner styles to left border and top-left - // corner, also removing bottom border and bottom-right corner styles - let borderMissingStyle = ''; - - if (this._rtl && (position !== St.Side.RIGHT)) { - borderMissingStyle = `border-right: ${borderWidth}px solid ${ - borderColor.to_string()};`; - } else if (!this._rtl && (position !== St.Side.LEFT)) { - borderMissingStyle = `border-left: ${borderWidth}px solid ${ - borderColor.to_string()};`; - } - - newStyle = borderMissingStyle; - - if (newStyle) { - // I do call set_style possibly twice so that only the background gets the transition. - // The transition-property css rules seems to be unsupported - this._dash._background.set_style(newStyle); - } - - // Customize background - const fixedTransparency = settings.transparencyMode === TransparencyMode.FIXED; - const defaultTransparency = settings.transparencyMode === TransparencyMode.DEFAULT; - if (!defaultTransparency && !fixedTransparency) { - this._transparency.enable(); - } else if (!defaultTransparency || settings.customBackgroundColor) { - newStyle = `${newStyle}background-color:${this._customizedBackground}; ` + - `border-color:${this._customizedBorder}; ` + - 'transition-delay: 0s; transition-duration: 0.250s;'; - this._dash._background.set_style(newStyle); - } - } - - _bindSettingsChanges() { - const keys = ['transparency-mode', - 'customize-alphas', - 'min-alpha', - 'max-alpha', - 'background-opacity', - 'custom-background-color', - 'background-color', - 'apply-custom-theme', - 'custom-theme-shrink', - 'custom-theme-running-dots', - 'extend-height', - 'force-straight-corner']; - - this._signalsHandler.add(...keys.map(key => [ - Docking.DockManager.settings, - `changed::${key}`, - () => this.updateCustomTheme(), - ])); - } -} -Signals.addSignalMethods(ThemeManager.prototype); - -/** - * The following class is based on the following upstream commit: - * https://git.gnome.org/browse/gnome-shell/commit/?id=447bf55e45b00426ed908b1b1035f472c2466956 - * Transparency when free-floating - */ -class Transparency { - constructor(dock) { - this._dash = dock.dash; - this._actor = this._dash._container; - this._backgroundActor = this._dash._background; - this._dockActor = dock; - this._dock = dock; - this._panel = Main.panel; - this._position = Utils.getPosition(); - - // All these properties are replaced with the ones in the .dummy-opaque - // and .dummy-transparent css classes - this._backgroundColor = '0,0,0'; - this._transparentAlpha = '0.2'; - this._opaqueAlpha = '1'; - this._transparentAlphaBorder = '0.1'; - this._opaqueAlphaBorder = '0.5'; - this._transparentTransition = '0ms'; - this._opaqueTransition = '0ms'; - this._base_actor_style = ''; - - this._signalsHandler = new Utils.GlobalSignalsHandler(); - this._trackedWindows = new Map(); - } - - enable() { - // ensure I never double-register/inject - // although it should never happen - this.disable(); - - this._base_actor_style = this._actor.get_style(); - if (!this._base_actor_style) - this._base_actor_style = ''; - - - let addedSignal = 'child-added'; - let removedSignal = 'child-removed'; - - // for compatibility with Gnome Shell 45 - if (GObject.signal_lookup('actor-added', global.window_group)) { - addedSignal = 'actor-added'; - removedSignal = 'actor-removed'; - } - - this._signalsHandler.addWithLabel(Labels.TRANSPARENCY, [ - global.window_group, - addedSignal, - this._onWindowActorAdded.bind(this), - ], [ - global.window_group, - removedSignal, - this._onWindowActorRemoved.bind(this), - ], [ - global.window_manager, - 'switch-workspace', - this._updateSolidStyle.bind(this), - ], [ - Main.overview, - 'hiding', - this._updateSolidStyle.bind(this), - ], [ - Main.overview, - 'showing', - this._updateSolidStyle.bind(this), - ]); - - // Window signals - global.window_group.get_children().filter(child => { - // An irrelevant window actor ('Gnome-shell') produces an error when the signals are - // disconnected, therefore do not add signals to it. - return child instanceof Meta.WindowActor && - child.get_meta_window().get_wm_class() !== 'Gnome-shell'; - }).forEach(function (win) { - this._onWindowActorAdded(null, win); - }, this); - - if (this._actor.get_stage()) - this._updateSolidStyle(); - - this._updateStyles(); - this._updateSolidStyle(); - - this.emit('transparency-enabled'); - } - - disable() { - // ensure I never double-register/inject - // although it should never happen - this._signalsHandler.removeWithLabel(Labels.TRANSPARENCY); - - for (const key of this._trackedWindows.keys()) { - this._trackedWindows.get(key).forEach(id => { - key.disconnect(id); - }); - } - this._trackedWindows.clear(); - - this.emit('transparency-disabled'); - } - - destroy() { - this.disable(); - this._signalsHandler.destroy(); - } - - _onWindowActorAdded(container, metaWindowActor) { - const signalIds = []; - ['notify::allocation', 'notify::visible'].forEach(s => { - signalIds.push(metaWindowActor.connect(s, this._updateSolidStyle.bind(this))); - }); - this._trackedWindows.set(metaWindowActor, signalIds); - } - - _onWindowActorRemoved(container, metaWindowActor) { - if (!this._trackedWindows.get(metaWindowActor)) - return; - - this._trackedWindows.get(metaWindowActor).forEach(id => { - metaWindowActor.disconnect(id); - }); - this._trackedWindows.delete(metaWindowActor); - this._updateSolidStyle(); - } - - _updateSolidStyle() { - const isNear = this._dockIsNear(); - if (isNear) { - this._backgroundActor.set_style(this._opaque_style); - this._dockActor.remove_style_class_name('transparent'); - this._dockActor.add_style_class_name('opaque'); - } else { - this._backgroundActor.set_style(this._transparent_style); - this._dockActor.remove_style_class_name('opaque'); - this._dockActor.add_style_class_name('transparent'); - } - - this.emit('solid-style-updated', isNear); - } - - _dockIsNear() { - if (this._dockActor.has_style_pseudo_class('overview')) - return false; - /* Get all the windows in the active workspace that are in the primary monitor and visible */ - const activeWorkspace = global.workspace_manager.get_active_workspace(); - const dash = this._dash; - const windows = activeWorkspace.list_windows().filter(metaWindow => { - return metaWindow.get_monitor() === dash._monitorIndex && - metaWindow.showing_on_its_workspace() && - metaWindow.get_window_type() !== Meta.WindowType.DESKTOP && - !metaWindow.skip_taskbar; - }); - - /* Check if at least one window is near enough to the panel. - * If the dock is hidden, we need to account for the space it would take - * up when it slides out. This is avoid an ugly transition. - * */ - let factor = 0; - if (!Docking.DockManager.settings.dockFixed && - this._dock.getDockState() === Docking.State.HIDDEN) - factor = 1; - const [leftCoord, topCoord] = this._actor.get_transformed_position(); - let threshold; - if (this._position === St.Side.LEFT) - threshold = leftCoord + this._actor.get_width() * (factor + 1); - else if (this._position === St.Side.RIGHT) - threshold = leftCoord - this._actor.get_width() * factor; - else if (this._position === St.Side.TOP) - threshold = topCoord + this._actor.get_height() * (factor + 1); - else - threshold = topCoord - this._actor.get_height() * factor; - - const scale = St.ThemeContext.get_for_stage(global.stage).scale_factor; - const isNearEnough = windows.some(metaWindow => { - let coord; - if (this._position === St.Side.LEFT) { - coord = metaWindow.get_frame_rect().x; - return coord < threshold + 5 * scale; - } else if (this._position === St.Side.RIGHT) { - coord = metaWindow.get_frame_rect().x + metaWindow.get_frame_rect().width; - return coord > threshold - 5 * scale; - } else if (this._position === St.Side.TOP) { - coord = metaWindow.get_frame_rect().y; - return coord < threshold + 5 * scale; - } else { - coord = metaWindow.get_frame_rect().y + metaWindow.get_frame_rect().height; - return coord > threshold - 5 * scale; - } - }); - - return isNearEnough; - } - - _updateStyles() { - this._getAlphas(); - - this._transparent_style = `${this._base_actor_style - }background-color: rgba(${ - this._backgroundColor}, ${this._transparentAlpha});` + - `border-color: rgba(${ - this._backgroundColor}, ${this._transparentAlphaBorder});` + - `transition-duration: ${this._transparentTransition}ms;`; - - this._opaque_style = `${this._base_actor_style - }background-color: rgba(${ - this._backgroundColor}, ${this._opaqueAlpha});` + - `border-color: rgba(${ - this._backgroundColor},${this._opaqueAlphaBorder});` + - `transition-duration: ${this._opaqueTransition}ms;`; - - this.emit('styles-updated'); - } - - setColor(color) { - this._backgroundColor = `${color.red},${color.green},${color.blue}`; - this._updateStyles(); - } - - _getAlphas() { - // Create dummy object and add to the uiGroup to get it to the stage - const dummyObject = new St.Bin({ - name: 'dashtodockContainer', - }); - Main.uiGroup.add_child(dummyObject); - - dummyObject.add_style_class_name('dummy-opaque'); - let themeNode = dummyObject.get_theme_node(); - this._opaqueAlpha = themeNode.get_background_color().alpha / 255; - this._opaqueAlphaBorder = themeNode.get_border_color(0).alpha / 255; - this._opaqueTransition = themeNode.get_transition_duration(); - - dummyObject.add_style_class_name('dummy-transparent'); - themeNode = dummyObject.get_theme_node(); - this._transparentAlpha = themeNode.get_background_color().alpha / 255; - this._transparentAlphaBorder = themeNode.get_border_color(0).alpha / 255; - this._transparentTransition = themeNode.get_transition_duration(); - - Main.uiGroup.remove_child(dummyObject); - - const {settings} = Docking.DockManager; - - if (settings.customizeAlphas) { - this._opaqueAlpha = settings.maxAlpha; - this._opaqueAlphaBorder = this._opaqueAlpha / 2; - this._transparentAlpha = settings.minAlpha; - this._transparentAlphaBorder = this._transparentAlpha / 2; - } - } -} -Signals.addSignalMethods(Transparency.prototype); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/utils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/utils.js deleted file mode 100755 index ccec00ae..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/utils.js +++ /dev/null @@ -1,695 +0,0 @@ -import { - Clutter, - GLib, - Gio, - GObject, - Meta, - Shell, - St, -} from './dependencies/gi.js'; - -import { - Docking, -} from './imports.js'; - -const {_gi: Gi} = imports; - -export const SignalsHandlerFlags = Object.freeze({ - NONE: 0, - CONNECT_AFTER: 1, -}); - -const GENERIC_KEY = Symbol('generic'); - -/** - * Simplify global signals and function injections handling - * abstract class - */ -const BasicHandler = class DashToDockBasicHandler { - static get genericKey() { - return GENERIC_KEY; - } - - constructor(parentObject) { - this._storage = Object.create(null); - - if (parentObject) { - if (!(parentObject.connect instanceof Function)) - throw new TypeError('Not a valid parent object'); - - if (!(parentObject instanceof GObject.Object) || - GObject.signal_lookup('destroy', parentObject.constructor.$gtype)) { - this._parentObject = parentObject; - this._destroyId = parentObject.connect('destroy', () => this.destroy()); - } - } - } - - add(...args) { - // Convert arguments object to array, concatenate with generic - // Call addWithLabel with ags as if they were passed arguments - this.addWithLabel(GENERIC_KEY, ...args); - } - - clear() { - Object.getOwnPropertySymbols(this._storage).forEach(label => - this.removeWithLabel(label)); - } - - destroy() { - this._parentObject?.disconnect(this._destroyId); - this._parentObject = null; - - this.clear(); - } - - block() { - Object.getOwnPropertySymbols(this._storage).forEach(label => - this.blockWithLabel(label)); - } - - unblock() { - Object.getOwnPropertySymbols(this._storage).forEach(label => - this.unblockWithLabel(label)); - } - - addWithLabel(label, ...args) { - if (typeof label !== 'symbol') - throw new Error(`Invalid label ${label}, must be a symbol`); - - let argsArray = [...args]; - if (argsArray.every(arg => !Array.isArray(arg))) - argsArray = [argsArray]; - - if (this._storage[label] === undefined) - this._storage[label] = []; - - // Skip first element of the arguments - for (const argArray of argsArray) { - if (argArray.length < 3) - throw new Error('Unexpected number of arguments'); - const item = this._storage[label]; - try { - item.push(this._create(...argArray)); - } catch (e) { - logError(e); - } - } - } - - removeWithLabel(label) { - this._storage[label]?.reverse().forEach(item => this._remove(item)); - delete this._storage[label]; - } - - blockWithLabel(label) { - (this._storage[label] || []).forEach(item => this._block(item)); - } - - unblockWithLabel(label) { - (this._storage[label] || []).forEach(item => this._unblock(item)); - } - - // Virtual methods to be implemented by subclass - - /** - * Create single element to be stored in the storage structure - * - * @param _object - * @param _element - * @param _callback - */ - _create(_object, _element, _callback) { - throw new GObject.NotImplementedError(`_create in ${this.constructor.name}`); - } - - /** - * Correctly delete single element - * - * @param _item - */ - _remove(_item) { - throw new GObject.NotImplementedError(`_remove in ${this.constructor.name}`); - } - - /** - * Block single element - * - * @param _item - */ - _block(_item) { - throw new GObject.NotImplementedError(`_block in ${this.constructor.name}`); - } - - /** - * Unblock single element - * - * @param _item - */ - _unblock(_item) { - throw new GObject.NotImplementedError(`_unblock in ${this.constructor.name}`); - } -}; - -/** - * Manage global signals - */ -export class GlobalSignalsHandler extends BasicHandler { - _create(object, event, callback, flags = SignalsHandlerFlags.NONE) { - if (!object) - throw new Error('Impossible to connect to an invalid object'); - - const after = flags === SignalsHandlerFlags.CONNECT_AFTER; - const connector = after ? object.connect_after : object.connect; - - if (!connector) { - throw new Error(`Requested to connect to signal '${event}', ` + - `but no implementation for 'connect${after ? '_after' : ''}' ` + - `found in ${object.constructor.name}`); - } - - const id = connector.call(object, event, callback); - - if (event === 'destroy' && object === this._parentObject) { - this._parentObject.disconnect(this._destroyId); - this._destroyId = - this._parentObject.connect('destroy', () => this.destroy()); - } - - return [object, id]; - } - - _remove(item) { - const [object, id] = item; - object.disconnect(id); - } - - _block(item) { - const [object, id] = item; - - if (object instanceof GObject.Object) - GObject.Object.prototype.block_signal_handler.call(object, id); - } - - _unblock(item) { - const [object, id] = item; - - if (object instanceof GObject.Object) - GObject.Object.prototype.unblock_signal_handler.call(object, id); - } -} - -/** - * Color manipulation utilities - */ -export class ColorUtils { - // Darken or brigthen color by a fraction dlum - // Each rgb value is modified by the same fraction. - // Return "#rrggbb" string - static ColorLuminance(r, g, b, dlum) { - let rgbString = '#'; - - rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(r * (1 + dlum), 0), 255)), 2); - rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(g * (1 + dlum), 0), 255)), 2); - rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(b * (1 + dlum), 0), 255)), 2); - - return rgbString; - } - - // Convert decimal to an hexadecimal string adding the desired padding - static _decimalToHex(d, padding) { - let hex = d.toString(16); - while (hex.length < padding) - hex = `0${hex}`; - return hex; - } - - // Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]). - // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV - // here with h = [0,1] instead of [0, 360] - // Accept either (h,s,v) independently or {h:h, s:s, v:v} object. - // Return {r:r, g:g, b:b} object. - static HSVtoRGB(h, s, v) { - if (arguments.length === 1) - ({s, v, h} = h); - - let r, g, b; - const c = v * s; - const h1 = h * 6; - const x = c * (1 - Math.abs(h1 % 2 - 1)); - const m = v - c; - - if (h1 <= 1) { - r = c + m; - g = x + m; - b = m; - } else if (h1 <= 2) { - r = x + m; - g = c + m; - b = m; - } else if (h1 <= 3) { - r = m; - g = c + m; - b = x + m; - } else if (h1 <= 4) { - r = m; - g = x + m; - b = c + m; - } else if (h1 <= 5) { - r = x + m; - g = m; - b = c + m; - } else { - r = c + m; - g = m; - b = x + m; - } - - return { - r: Math.round(r * 255), - g: Math.round(g * 255), - b: Math.round(b * 255), - }; - } - - // Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]). - // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV - // here with h = [0,1] instead of [0, 360] - // Accept either (r,g,b) independently or {r:r, g:g, b:b} object. - // Return {h:h, s:s, v:v} object. - static RGBtoHSV(r, g, b) { - if (arguments.length === 1) - ({r, g, b} = r); - - let h, s; - - const M = Math.max(r, g, b); - const m = Math.min(r, g, b); - const c = M - m; - - if (c === 0) - h = 0; - else if (M === r) - h = ((g - b) / c) % 6; - else if (M === g) - h = (b - r) / c + 2; - else - h = (r - g) / c + 4; - - h /= 6; - const v = M / 255; - if (M !== 0) - s = c / M; - else - s = 0; - - return { - h, - s, - v, - }; - } -} - -/** - * Manage function injection: both instances and prototype can be overridden - * and restored - */ -export class InjectionsHandler extends BasicHandler { - _create(object, name, injectedFunction) { - const original = object[name]; - - if (!(original instanceof Function)) - throw new Error(`Virtual function ${name}() is not available for ${object}`); - - object[name] = function (...args) { - return injectedFunction.call(this, original, ...args); - }; - return [object, name, original]; - } - - _remove(item) { - const [object, name, original] = item; - object[name] = original; - } -} - -/** - * Manage vfunction injection: both instances and prototype can be overridden - * and restored - */ -export class VFuncInjectionsHandler extends BasicHandler { - _create(prototype, name, injectedFunction) { - const original = prototype[`vfunc_${name}`]; - if (!(original instanceof Function)) - throw new Error(`Virtual function ${name} is not available for ${prototype}`); - this._replaceVFunc(prototype, name, injectedFunction); - return [prototype, name]; - } - - _remove(item) { - const [prototype, name] = item; - const originalVFunc = prototype[`vfunc_${name}`]; - try { - // This may fail if trying to reset to a never-overridden vfunc - // as gjs doesn't consider it a function, even if it's true that - // originalVFunc instanceof Function. - this._replaceVFunc(prototype, name, originalVFunc); - } catch { - try { - this._replaceVFunc(prototype, name, function (...args) { - // eslint-disable-next-line no-invalid-this - return originalVFunc.call(this, ...args); - }); - } catch (e) { - logError(e, `Removing vfunc_${name}`); - } - } - } - - _replaceVFunc(prototype, name, func) { - if (Gi.gobject_prototype_symbol && Gi.gobject_prototype_symbol in prototype) - prototype = prototype[Gi.gobject_prototype_symbol]; - - return prototype[Gi.hook_up_vfunc_symbol](name, func); - } -} - -/** - * Manage properties injection: both instances and prototype can be overridden - * and restored - */ -export class PropertyInjectionsHandler extends BasicHandler { - _create(instance, name, injectedPropertyDescriptor) { - if (!(name in instance)) - throw new Error(`Object ${instance} has no '${name}' property`); - - const {prototype} = instance.constructor; - const originalPropertyDescriptor = Object.getOwnPropertyDescriptor(prototype, name) ?? - Object.getOwnPropertyDescriptor(instance, name); - - Object.defineProperty(instance, name, { - ...originalPropertyDescriptor, - ...injectedPropertyDescriptor, - ...{configurable: true}, - }); - return [instance, name, originalPropertyDescriptor]; - } - - _remove(item) { - const [instance, name, originalPropertyDescriptor] = item; - if (originalPropertyDescriptor) - Object.defineProperty(instance, name, originalPropertyDescriptor); - else - delete instance[name]; - } -} - -/** - * Return the actual position reverseing left and right in rtl - */ -export function getPosition() { - const position = Docking.DockManager.settings.dockPosition; - if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) { - if (position === St.Side.LEFT) - return St.Side.RIGHT; - else if (position === St.Side.RIGHT) - return St.Side.LEFT; - } - return position; -} - -/** - * @param cr - * @param x - * @param y - * @param width - * @param height - * @param isRoundLeft - * @param isRoundRight - * @param stroke - * @param fill - */ -export function drawRoundedLine(cr, x, y, width, height, isRoundLeft, isRoundRight, stroke, fill) { - if (height > width) { - y += Math.floor((height - width) / 2.0); - height = width; - } - - height = 2.0 * Math.floor(height / 2.0); - - const leftRadius = isRoundLeft ? height / 2.0 : 0.0; - const rightRadius = isRoundRight ? height / 2.0 : 0.0; - - cr.moveTo(x + width - rightRadius, y); - cr.lineTo(x + leftRadius, y); - if (isRoundLeft) - cr.arcNegative(x + leftRadius, y + leftRadius, leftRadius, -Math.PI / 2, Math.PI / 2); - else - cr.lineTo(x, y + height); - cr.lineTo(x + width - rightRadius, y + height); - if (isRoundRight) - cr.arcNegative(x + width - rightRadius, y + rightRadius, rightRadius, Math.PI / 2, -Math.PI / 2); - else - cr.lineTo(x + width, y); - cr.closePath(); - - if (fill) { - cr.setSource(fill); - cr.fillPreserve(); - } - if (stroke) - cr.setSource(stroke); - cr.stroke(); -} - -/** - * Convert a signal handler with n value parameters (that is, excluding the - * signal source parameter) to an array of n handlers that are each responsible - * for receiving one of the n values and calling the original handler with the - * most up-to-date arguments. - * - * @param handler - */ -export function splitHandler(handler) { - if (handler.length > 30) - throw new Error('too many parameters'); - - const count = handler.length - 1; - let missingValueBits = (1 << count) - 1; - const values = Array.from({length: count}); - return values.map((_ignored, i) => { - const mask = ~(1 << i); - return (obj, value) => { - values[i] = value; - missingValueBits &= mask; - if (missingValueBits === 0) - handler(obj, ...values); - }; - }); -} - -/** - * Construct a map of gtk application window object paths to MetaWindows. - */ -export function getWindowsByObjectPath() { - const windowsByObjectPath = new Map(); - const {workspaceManager} = global; - const workspaces = [...new Array(workspaceManager.nWorkspaces)].map( - (_c, i) => workspaceManager.get_workspace_by_index(i)); - - workspaces.forEach(ws => { - ws.list_windows().forEach(w => { - const path = w.get_gtk_window_object_path(); - if (path) - windowsByObjectPath.set(path, w); - }); - }); - - return windowsByObjectPath; -} - -/** - * Re-implements shell_app_compare so that can be used to resort running apps - * - * @param appA - * @param appB - */ -export function shellAppCompare(appA, appB) { - if (appA.state !== appB.state) { - if (appA.state === Shell.AppState.RUNNING) - return -1; - return 1; - } - - const windowsA = appA.get_windows(); - const windowsB = appB.get_windows(); - - const isMinimized = windows => !windows.some(w => w.showing_on_its_workspace()); - const minimizedB = isMinimized(windowsB); - if (isMinimized(windowsA) !== minimizedB) { - if (minimizedB) - return -1; - return 1; - } - - if (appA.state === Shell.AppState.RUNNING) { - if (windowsA.length && !windowsB.length) - return -1; - else if (!windowsA.length && windowsB.length) - return 1; - - const lastUserTime = windows => - Math.max(...windows.map(w => w.get_user_time())); - return lastUserTime(windowsB) - lastUserTime(windowsA); - } - - return 0; -} - -/** - * Re-implements shell_app_compare_windows - * - * @param winA - * @param winB - */ -export function shellWindowsCompare(winA, winB) { - const activeWorkspace = global.workspaceManager.get_active_workspace(); - const wsA = winA.get_workspace() === activeWorkspace; - const wsB = winB.get_workspace() === activeWorkspace; - - if (wsA && !wsB) - return -1; - else if (!wsA && wsB) - return 1; - - const visA = winA.showing_on_its_workspace(); - const visB = winB.showing_on_its_workspace(); - - if (visA && !visB) - return -1; - else if (!visA && visB) - return 1; - - return winB.get_user_time() - winA.get_user_time(); -} - -export const CancellableChild = GObject.registerClass({ - Properties: { - 'parent': GObject.ParamSpec.object( - 'parent', 'parent', 'parent', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, - Gio.Cancellable.$gtype), - }, -}, -class CancellableChild extends Gio.Cancellable { - _init(parent) { - if (parent && !(parent instanceof Gio.Cancellable)) - throw TypeError('Not a valid cancellable'); - - super._init({parent}); - - if (parent?.is_cancelled()) { - this.cancel(); - return; - } - - this._connectToParent(); - } - - _connectToParent() { - this._connectId = this.parent?.connect(() => { - this._realCancel(); - - if (this._disconnectIdle) - return; - - this._disconnectIdle = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { - delete this._disconnectIdle; - this._disconnectFromParent(); - return GLib.SOURCE_REMOVE; - }); - }); - } - - _disconnectFromParent() { - if (this._connectId && !this._disconnectIdle) { - this.parent.disconnect(this._connectId); - delete this._connectId; - } - } - - _realCancel() { - Gio.Cancellable.prototype.cancel.call(this); - } - - cancel() { - this._disconnectFromParent(); - this._realCancel(); - } -}); - -/** - * - */ -export function getMonitorManager() { - return global.backend.get_monitor_manager?.() ?? Meta.MonitorManager.get(); -} - -/** - * @param laterType - * @param callback - */ -export function laterAdd(laterType, callback) { - return global.compositor?.get_laters?.().add(laterType, callback) ?? - Meta.later_add(laterType, callback); -} - -/** - * @param id - */ -export function laterRemove(id) { - if (global.compositor?.get_laters) - global.compositor?.get_laters().remove(id); - else - Meta.later_remove(id); -} - -/** - * Up to Gnome Shell 45, the Cairo Context object didn't export the - * `setSourceColor()` method, so Clutter included a function call for - * that, written in C. In Gnome Shell 46, the method was finally exported, - * so that function was removed. - * - * This function is, thus, required for Gnome Shell 45 compatibility. - * - * @param {*} cr A cairo context - * @param {*} sourceColor The new color for source - */ -export function cairoSetSourceColor(cr, sourceColor) { - if (Clutter.cairo_set_source_color) - Clutter.cairo_set_source_color(cr, sourceColor); - else - cr.setSourceColor(sourceColor); -} - -/** - * Specifies if the system supports extended barriers. This function - * is required for Gnome Shell 45 compatibility, which used - * `global.display.supports_extended_barriers`. Gnome Shell 46 moved - * that into global.backend.capabilities. - * - * @returns True if the system supports extended barriers. - */ -export function supportsExtendedBarriers() { - if (global.display.supports_extended_barriers) - return global.display.supports_extended_barriers(); - return !!(global.backend.capabilities & Meta.BackendCapabilities.BARRIERS); -} - -export function addActor(element, actor) { - if (element.add_actor) - element.add_actor(actor); - else - element.add_child(actor); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/windowPreview.js b/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/windowPreview.js deleted file mode 100755 index 75459b52..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/dash-to-dock@micxgx.gmail.com/windowPreview.js +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Credits: - * This file is based on code from the Dash to Panel extension by Jason DeRose - * and code from the Taskbar extension by Zorin OS - * Some code was also adapted from the upstream Gnome Shell source code. - */ - -import { - Clutter, - GLib, - GObject, - Meta, - St, -} from './dependencies/gi.js'; - -import { - BoxPointer, - Main, - PopupMenu, - Workspace, -} from './dependencies/shell/ui.js'; - -import { - Docking, - Theming, - Utils, -} from './imports.js'; - -const PREVIEW_MAX_WIDTH = 250; -const PREVIEW_MAX_HEIGHT = 150; - -const PREVIEW_ANIMATION_DURATION = 250; -const MAX_PREVIEW_GENERATION_ATTEMPTS = 15; - -const MENU_MARGINS = 10; - -export class WindowPreviewMenu extends PopupMenu.PopupMenu { - constructor(source) { - super(source, 0.5, Utils.getPosition()); - - // We want to keep the item hovered while the menu is up - this.blockSourceEvents = true; - - this._source = source; - this._app = this._source.app; - const workArea = Main.layoutManager.getWorkAreaForMonitor( - this._source.monitorIndex); - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - - this.actor.add_style_class_name('app-menu'); - this.actor.set_style( - `max-width: ${Math.round(workArea.width / scaleFactor) - MENU_MARGINS}px; ` + - `max-height: ${Math.round(workArea.height / scaleFactor) - MENU_MARGINS}px;`); - this.actor.hide(); - - // Chain our visibility and lifecycle to that of the source - this._mappedId = this._source.connect('notify::mapped', () => { - if (!this._source.mapped) - this.close(); - }); - this._destroyId = this._source.connect('destroy', this.destroy.bind(this)); - - Utils.addActor(Main.uiGroup, this.actor); - - this.connect('destroy', this._onDestroy.bind(this)); - } - - _redisplay() { - if (this._previewBox) - this._previewBox.destroy(); - this._previewBox = new WindowPreviewList(this._source); - this.addMenuItem(this._previewBox); - this._previewBox._redisplay(); - } - - popup() { - const windows = this._source.getInterestingWindows(); - if (windows.length > 0) { - this._redisplay(); - this.open(BoxPointer.PopupAnimation.FULL); - this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); - this._source.emit('sync-tooltip'); - } - } - - _onDestroy() { - if (this._mappedId) - this._source.disconnect(this._mappedId); - - if (this._destroyId) - this._source.disconnect(this._destroyId); - } -} - -class WindowPreviewList extends PopupMenu.PopupMenuSection { - constructor(source) { - super(); - this.actor = new St.ScrollView({ - name: 'dashtodockWindowScrollview', - hscrollbar_policy: St.PolicyType.NEVER, - vscrollbar_policy: St.PolicyType.NEVER, - overlay_scrollbars: true, - enable_mouse_scrolling: true, - }); - - this.actor.connect('scroll-event', this._onScrollEvent.bind(this)); - - const position = Utils.getPosition(); - this.isHorizontal = position === St.Side.BOTTOM || position === St.Side.TOP; - this.box.set_vertical(!this.isHorizontal); - this.box.set_name('dashtodockWindowList'); - Utils.addActor(this.actor, this.box); - this.actor._delegate = this; - - this._shownInitially = false; - - this._source = source; - this.app = source.app; - - this._redisplayId = Main.initializeDeferredWork(this.actor, this._redisplay.bind(this)); - - this.actor.connect('destroy', this._onDestroy.bind(this)); - this._stateChangedId = this.app.connect('windows-changed', - this._queueRedisplay.bind(this)); - } - - _queueRedisplay() { - Main.queueDeferredWork(this._redisplayId); - } - - _onScrollEvent(actor, event) { - // Event coordinates are relative to the stage but can be transformed - // as the actor will only receive events within his bounds. - const [stageX, stageY] = event.get_coords(); - const [,, eventY] = actor.transform_stage_point(stageX, stageY); - const [, actorH] = actor.get_size(); - - // If the scroll event is within a 1px margin from - // the relevant edge of the actor, let the event propagate. - if (eventY >= actorH - 2) - return Clutter.EVENT_PROPAGATE; - - // Skip to avoid double events mouse - if (event.is_pointer_emulated()) - return Clutter.EVENT_STOP; - - let adjustment, delta; - - if (this.isHorizontal) - adjustment = this.actor.get_hscroll_bar().get_adjustment(); - else - adjustment = this.actor.get_vscroll_bar().get_adjustment(); - - const increment = adjustment.step_increment; - - switch (event.get_scroll_direction()) { - case Clutter.ScrollDirection.UP: - delta = -increment; - break; - case Clutter.ScrollDirection.DOWN: - delta = Number(increment); - break; - case Clutter.ScrollDirection.SMOOTH: { - const [dx, dy] = event.get_scroll_delta(); - delta = dy * increment; - delta += dx * increment; - break; - } - } - - adjustment.set_value(adjustment.get_value() + delta); - - return Clutter.EVENT_STOP; - } - - _onDestroy() { - this.app.disconnect(this._stateChangedId); - this._stateChangedId = 0; - } - - _createPreviewItem(window) { - const preview = new WindowPreviewMenuItem(window, Utils.getPosition()); - return preview; - } - - _redisplay() { - const children = this._getMenuItems().filter(actor => { - return actor._window; - }); - - // Windows currently on the menu - const oldWin = children.map(actor => { - return actor._window; - }); - - // All app windows with a static order - const newWin = this._source.getInterestingWindows().sort((a, b) => - a.get_stable_sequence() > b.get_stable_sequence()); - - const addedItems = []; - const removedActors = []; - - let newIndex = 0; - let oldIndex = 0; - - while (newIndex < newWin.length || oldIndex < oldWin.length) { - const currentOldWin = oldWin[oldIndex]; - const currentNewWin = newWin[newIndex]; - - // No change at oldIndex/newIndex - if (currentOldWin === currentNewWin) { - oldIndex++; - newIndex++; - continue; - } - - // Window removed at oldIndex - if (currentOldWin && !newWin.includes(currentOldWin)) { - removedActors.push(children[oldIndex]); - oldIndex++; - continue; - } - - // Window added at newIndex - if (currentNewWin && !oldWin.includes(currentNewWin)) { - addedItems.push({ - item: this._createPreviewItem(currentNewWin), - pos: newIndex, - }); - newIndex++; - continue; - } - - // Window moved - const insertHere = newWin[newIndex + 1] && - newWin[newIndex + 1] === currentOldWin; - const alreadyRemoved = removedActors.reduce((result, actor) => - result || actor._window === currentNewWin, false); - - if (insertHere || alreadyRemoved) { - addedItems.push({ - item: this._createPreviewItem(currentNewWin), - pos: newIndex + removedActors.length, - }); - newIndex++; - } else { - removedActors.push(children[oldIndex]); - oldIndex++; - } - } - - for (let i = 0; i < addedItems.length; i++) { - this.addMenuItem(addedItems[i].item, - addedItems[i].pos); - } - - for (let i = 0; i < removedActors.length; i++) { - const item = removedActors[i]; - if (this._shownInitially) - item._animateOutAndDestroy(); - else - item.actor.destroy(); - } - - // Skip animations on first run when adding the initial set - // of items, to avoid all items zooming in at once - const animate = this._shownInitially; - - if (!this._shownInitially) - this._shownInitially = true; - - for (let i = 0; i < addedItems.length; i++) - addedItems[i].item.show(animate); - - // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 - // Without it, StBoxLayout may use a stale size cache - this.box.queue_relayout(); - - if (newWin.length < 1) - this._getTopMenu().close(~0); - - // As for upstream: - // St.ScrollView always requests space horizontally for a possible vertical - // scrollbar if in AUTOMATIC mode. Doing better would require implementation - // of width-for-height in St.BoxLayout and St.ScrollView. This looks bad - // when we *don't* need it, so turn off the scrollbar when that's true. - // Dynamic changes in whether we need it aren't handled properly. - const needsScrollbar = this._needsScrollbar(); - const scrollbarPolicy = needsScrollbar - ? St.PolicyType.AUTOMATIC : St.PolicyType.NEVER; - if (this.isHorizontal) - this.actor.hscrollbarPolicy = scrollbarPolicy; - else - this.actor.vscrollbarPolicy = scrollbarPolicy; - - if (needsScrollbar) - this.actor.add_style_pseudo_class('scrolled'); - else - this.actor.remove_style_pseudo_class('scrolled'); - } - - _needsScrollbar() { - const topMenu = this._getTopMenu(); - const topThemeNode = topMenu.actor.get_theme_node(); - if (this.isHorizontal) { - const [topMinWidth_, topNaturalWidth] = - topMenu.actor.get_preferred_width(-1); - const topMaxWidth = topThemeNode.get_max_width(); - return topMaxWidth >= 0 && topNaturalWidth >= topMaxWidth; - } else { - const [topMinHeight_, topNaturalHeight] = - topMenu.actor.get_preferred_height(-1); - const topMaxHeight = topThemeNode.get_max_height(); - return topMaxHeight >= 0 && topNaturalHeight >= topMaxHeight; - } - } - - isAnimatingOut() { - return this.actor.get_children().reduce((result, actor) => { - return result || actor.animatingOut; - }, false); - } -} - -export const WindowPreviewMenuItem = GObject.registerClass( -class WindowPreviewMenuItem extends PopupMenu.PopupBaseMenuItem { - _init(window, position, params) { - super._init(params); - - this._window = window; - this._destroyId = 0; - this._windowAddedId = 0; - - // We don't want this: it adds spacing on the left of the item. - this.remove_child(this._ornamentIcon); - this.add_style_class_name('dashtodock-app-well-preview-menu-item'); - this.add_style_class_name(Theming.PositionStyleClass[position]); - if (Docking.DockManager.settings.customThemeShrink) - this.add_style_class_name('shrink'); - - // Now we don't have to set PREVIEW_MAX_WIDTH and PREVIEW_MAX_HEIGHT as - // preview size - that made all kinds of windows either stretched or - // squished (aspect ratio problem) - this._cloneBin = new St.Bin(); - - this._updateWindowPreviewSize(); - - // TODO: improve the way the closebutton is layout. Just use some padding - // for the moment. - this._cloneBin.set_style('padding-bottom: 0.5em'); - - const buttonLayout = Meta.prefs_get_button_layout(); - this.closeButton = new St.Button({ - style_class: 'window-close', - opacity: 0, - x_expand: true, - y_expand: true, - x_align: buttonLayout.left_buttons.includes(Meta.ButtonFunction.CLOSE) - ? Clutter.ActorAlign.START : Clutter.ActorAlign.END, - y_align: Clutter.ActorAlign.START, - }); - Utils.addActor(this.closeButton, new St.Icon({icon_name: 'window-close-symbolic'})); - this.closeButton.connect('clicked', () => this._closeWindow()); - - const overlayGroup = new Clutter.Actor({ - layout_manager: new Clutter.BinLayout(), - y_expand: true, - }); - - overlayGroup.add_child(this._cloneBin); - overlayGroup.add_child(this.closeButton); - - const label = new St.Label({text: window.get_title()}); - label.set_style(`max-width: ${PREVIEW_MAX_WIDTH}px`); - const labelBin = new St.Bin({ - child: label, - x_align: Clutter.ActorAlign.CENTER, - }); - - this._windowTitleId = this._window.connect('notify::title', () => { - label.set_text(this._window.get_title()); - }); - - const box = new St.BoxLayout({ - vertical: true, - reactive: true, - x_expand: true, - }); - - if (box.add) { - box.add(overlayGroup); - box.add(labelBin); - } else { - box.add_child(overlayGroup); - box.add_child(labelBin); - } - this._box = box; - this.add_child(box); - - this._cloneTexture(window); - - this.connect('destroy', this._onDestroy.bind(this)); - } - - vfunc_style_changed() { - super.vfunc_style_changed(); - - // For some crazy clutter / St reason we can't just have this handled - // automatically or here via vfunc_allocate + vfunc_get_preferred_* - // because if we do so, the St paddings on first / last child are lost - const themeNode = this.get_theme_node(); - let [minWidth, naturalWidth] = this._box.get_preferred_width(-1); - let [minHeight, naturalHeight] = this._box.get_preferred_height(naturalWidth); - [minWidth, naturalWidth] = themeNode.adjust_preferred_width(minWidth, naturalWidth); - [minHeight, naturalHeight] = themeNode.adjust_preferred_height(minHeight, naturalHeight); - this.set({minWidth, naturalWidth, minHeight, naturalHeight}); - } - - _getWindowPreviewSize() { - const emptySize = [0, 0, 0]; - - const mutterWindow = this._window.get_compositor_private(); - if (!mutterWindow?.get_texture()) - return emptySize; - - const [width, height] = mutterWindow.get_size(); - if (!width || !height) - return emptySize; - - let {previewSizeScale: scale} = Docking.DockManager.settings; - if (!scale) { - // a simple example with 1680x1050: - // * 250/1680 = 0,1488 - // * 150/1050 = 0,1429 - // => scale is 0,1429 - scale = Math.min(1.0, PREVIEW_MAX_WIDTH / width, PREVIEW_MAX_HEIGHT / height); - } - - scale *= St.ThemeContext.get_for_stage(global.stage).scaleFactor; - - // width and height that we wanna multiply by scale - return [width, height, scale]; - } - - _updateWindowPreviewSize() { - // This gets the actual windows size for the preview - [this._width, this._height, this._scale] = this._getWindowPreviewSize(); - this._cloneBin.set_size(this._width * this._scale, this._height * this._scale); - } - - _cloneTexture(metaWin) { - // Newly-created windows are added to a workspace before - // the compositor finds out about them... - if (!this._width || !this._height) { - this._cloneTextureLater = Utils.laterAdd(Meta.LaterType.BEFORE_REDRAW, () => { - // Check if there's still a point in getting the texture, - // otherwise this could go on indefinitely - this._updateWindowPreviewSize(); - - if (this._width && this._height) { - this._cloneTexture(metaWin); - } else { - this._cloneAttempt = (this._cloneAttempt || 0) + 1; - if (this._cloneAttempt < MAX_PREVIEW_GENERATION_ATTEMPTS) - return GLib.SOURCE_CONTINUE; - } - delete this._cloneTextureLater; - return GLib.SOURCE_REMOVE; - }); - return; - } - - const mutterWindow = metaWin.get_compositor_private(); - const clone = new Clutter.Clone({ - source: mutterWindow, - reactive: true, - width: this._width * this._scale, - height: this._height * this._scale, - }); - - // when the source actor is destroyed, i.e. the window closed, first destroy the clone - // and then destroy the menu item (do this animating out) - this._destroyId = mutterWindow.connect('destroy', () => { - clone.destroy(); - this._destroyId = 0; // avoid to try to disconnect this signal from mutterWindow in _onDestroy(), - // as the object was just destroyed - this._animateOutAndDestroy(); - }); - - this._clone = clone; - this._mutterWindow = mutterWindow; - this._cloneBin.set_child(this._clone); - - this._clone.connect('destroy', () => { - if (this._destroyId) { - mutterWindow.disconnect(this._destroyId); - this._destroyId = 0; - } - this._clone = null; - }); - } - - _windowCanClose() { - return this._window.can_close() && - !this._hasAttachedDialogs(); - } - - _closeWindow() { - this._workspace = this._window.get_workspace(); - - // This mechanism is copied from the workspace.js upstream code - // It forces window activation if the windows don't get closed, - // for instance because asking user confirmation, by monitoring the opening of - // such additional confirmation window - this._windowAddedId = this._workspace.connect('window-added', - this._onWindowAdded.bind(this)); - - this.deleteAllWindows(); - } - - deleteAllWindows() { - // Delete all windows, starting from the bottom-most (most-modal) one - // let windows = this._window.get_compositor_private().get_children(); - const windows = this._clone.get_children(); - for (let i = windows.length - 1; i >= 1; i--) { - const realWindow = windows[i].source; - const metaWindow = realWindow.meta_window; - - metaWindow.delete(global.get_current_time()); - } - - this._window.delete(global.get_current_time()); - } - - _onWindowAdded(workspace, win) { - const metaWindow = this._window; - - if (win.get_transient_for() === metaWindow) { - workspace.disconnect(this._windowAddedId); - this._windowAddedId = 0; - - // use an idle handler to avoid mapping problems - - // see comment in Workspace._windowAdded - const activationEvent = Clutter.get_current_event(); - this._windowAddedLater = Utils.laterAdd(Meta.LaterType.BEFORE_REDRAW, () => { - delete this._windowAddedLater; - this.emit('activate', activationEvent); - return GLib.SOURCE_REMOVE; - }); - } - } - - _hasAttachedDialogs() { - // count trasient windows - let n = 0; - this._window.foreach_transient(() => { - n++; - }); - return n > 0; - } - - vfunc_key_focus_in() { - super.vfunc_key_focus_in(); - this._showCloseButton(); - } - - vfunc_key_focus_out() { - super.vfunc_key_focus_out(); - this._hideCloseButton(); - } - - vfunc_enter_event(crossingEvent) { - this._showCloseButton(); - return super.vfunc_enter_event(crossingEvent); - } - - vfunc_leave_event(crossingEvent) { - this._hideCloseButton(); - return super.vfunc_leave_event(crossingEvent); - } - - _idleToggleCloseButton() { - this._idleToggleCloseId = 0; - - this._hideCloseButton(); - - return GLib.SOURCE_REMOVE; - } - - _showCloseButton() { - if (this._windowCanClose()) { - this.closeButton.show(); - this.closeButton.remove_all_transitions(); - this.closeButton.ease({ - opacity: 255, - duration: Workspace.WINDOW_OVERLAY_FADE_TIME, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - } - - _hideCloseButton() { - if (this.closeButton.has_pointer || - this.get_children().some(a => a.has_pointer)) - return; - - this.closeButton.remove_all_transitions(); - this.closeButton.ease({ - opacity: 0, - duration: Workspace.WINDOW_OVERLAY_FADE_TIME, - mode: Clutter.AnimationMode.EASE_IN_QUAD, - }); - } - - show(animate) { - const fullWidth = this.get_width(); - - this.opacity = 0; - this.set_width(0); - - const time = animate ? PREVIEW_ANIMATION_DURATION : 0; - this.remove_all_transitions(); - this.ease({ - opacity: 255, - width: fullWidth, - duration: time, - mode: Clutter.AnimationMode.EASE_IN_OUT_QUAD, - }); - } - - _animateOutAndDestroy() { - this.remove_all_transitions(); - this.ease({ - opacity: 0, - duration: PREVIEW_ANIMATION_DURATION, - }); - - this.ease({ - width: 0, - height: 0, - duration: PREVIEW_ANIMATION_DURATION, - delay: PREVIEW_ANIMATION_DURATION, - onComplete: () => this.destroy(), - }); - } - - activate() { - this._getTopMenu().close(); - Main.activateWindow(this._window); - } - - _onDestroy() { - if (this._cloneTextureLater) { - Utils.laterRemove(this._cloneTextureLater); - delete this._cloneTextureLater; - } - - if (this._windowAddedLater) { - Utils.laterRemove(this._windowAddedLater); - delete this._windowAddedLater; - } - - if (this._windowAddedId > 0) { - this._workspace.disconnect(this._windowAddedId); - this._windowAddedId = 0; - } - - if (this._destroyId > 0) { - this._mutterWindow.disconnect(this._destroyId); - this._destroyId = 0; - } - - if (this._windowTitleId > 0) { - this._window.disconnect(this._windowTitleId); - this._windowTitleId = 0; - } - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/extension.js deleted file mode 100644 index 992cf607..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/extension.js +++ /dev/null @@ -1,302 +0,0 @@ -/* extension.js - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -import GLib from 'gi://GLib' -import Clutter from 'gi://Clutter' -import St from 'gi://St' - -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js' -import * as Main from 'resource:///org/gnome/shell/ui/main.js' -const MainPanel = Main.panel - -import { - getCurrentLocale, - getCurrentCalendar, - getCurrentTimezone, - updateLevel, - TEXT_ALIGN_CENTER, -} from './utils/general.js' -import { FormatterManager } from './utils/formatter.js' -import * as prefFields from './utils/prefFields.js' - -let PATTERN = '' -let USE_DEFAULT_LOCALE = true -let USE_DEFAULT_CALENDAR = true -let USE_DEFAULT_TIMEZONE = true -let CUSTOM_LOCALE = '' -let CUSTOM_CALENDAR = '' -let CUSTOM_TIMEZONE = '' -let REMOVE_MESSAGES_INDICATOR = false -let APPLY_ALL_PANELS = false -let FONT_SIZE = 1 -let EVERY = null -let TEXT_ALIGN_MODE = '' - -function _getDateMenuButton(panel) { - return panel.statusArea.dateMenu.get_children()[0] -} - -export default class DateMenuFormatter extends Extension { - constructor(metadata) { - super(metadata) - - this.formatters = null - this._formatters_load_promise = null - this._displays = null - this._timerId = -1 - this._settingsChangedId = null - this._dashToPanelConnection = null - this._formatter = null - this._update = true - } - - _createDisplay() { - const display = new St.Label({ - style_class: 'clock', - style: 'font-size: 9pt; text-align: center', - }) - display.clutter_text.x_align = Clutter.ActorAlign.CENTER - display.clutter_text.y_align = Clutter.ActorAlign.CENTER - display.text = '...' - return display - } - - _loadSettings() { - this._settings = this.getSettings() - this._settingsChangedId = this._settings.connect( - 'changed', - this._onSettingsChange.bind(this) - ) - this._onSettingsChange() - } - - _fetchSettings() { - PATTERN = this._settings.get_string(prefFields.PATTERN) - - REMOVE_MESSAGES_INDICATOR = this._settings.get_boolean( - prefFields.REMOVE_MESSAGES_INDICATOR - ) - USE_DEFAULT_LOCALE = this._settings.get_boolean( - prefFields.USE_DEFAULT_LOCALE - ) - CUSTOM_LOCALE = this._settings.get_string(prefFields.CUSTOM_LOCALE) - USE_DEFAULT_CALENDAR = this._settings.get_boolean( - prefFields.USE_DEFAULT_CALENDAR - ) - CUSTOM_CALENDAR = this._settings.get_string(prefFields.CUSTOM_CALENDAR) - USE_DEFAULT_TIMEZONE = this._settings.get_boolean( - prefFields.USE_DEFAULT_TIMEZONE - ) - CUSTOM_TIMEZONE = this._settings.get_string(prefFields.CUSTOM_TIMEZONE) - APPLY_ALL_PANELS = this._settings.get_boolean(prefFields.APPLY_ALL_PANELS) - FONT_SIZE = this._settings.get_int(prefFields.FONT_SIZE) - - TEXT_ALIGN_MODE = - this._settings.get_string(prefFields.TEXT_ALIGN) || TEXT_ALIGN_CENTER - - const curLvl = this._settings.get_int(prefFields.UPDATE_LEVEL) - if (EVERY.lvl !== curLvl) { - EVERY = updateLevel(curLvl) - if (this._timerId !== -1) this.restart() - } - - const locale = USE_DEFAULT_LOCALE ? getCurrentLocale() : CUSTOM_LOCALE - const calendar = USE_DEFAULT_CALENDAR - ? getCurrentCalendar() - : CUSTOM_CALENDAR - const timezone = USE_DEFAULT_TIMEZONE - ? getCurrentTimezone() - : CUSTOM_TIMEZONE - - this._formatters_load_promise.then(() => { - const formatterKey = this._settings.get_string(prefFields.FORMATTER) - const formatter = this.formatters.getFormatter(formatterKey) - if (formatter) { - this._formatter = new formatter(timezone, locale, calendar) - } - }) - } - - _removeIndicator(panels) { - panels.forEach((panel) => { - if (panel.statusArea.dateMenu._indicator.get_parent()) - _getDateMenuButton(panel).remove_child( - panel.statusArea.dateMenu._indicator - ) - }) - } - - _restoreIndicator(panels) { - panels.forEach((panel) => { - if (!panel.statusArea.dateMenu._indicator.get_parent()) - _getDateMenuButton(panel).insert_child_at_index( - panel.statusArea.dateMenu._indicator, - 2 - ) - }) - } - - // returns affected and unaffected panels based on settings and Dash To Panel availability - _getPanels() { - if (!global.dashToPanel) return [[MainPanel], []] - else if (APPLY_ALL_PANELS) { - return [global.dashToPanel.panels, []] - } else { - // MainPanel is not the same as primary Dash To Panel panel, but their dateMenus are the same - return [ - [MainPanel], - global.dashToPanel.panels.filter( - (panel) => panel.statusArea.dateMenu != MainPanel.statusArea.dateMenu - ), - ] - } - } - - _enableOn(panels) { - panels.forEach((panel, idx) => { - const dateMenuButton = _getDateMenuButton(panel) - if (!this._displays[idx].get_parent()) { - dateMenuButton.insert_child_at_index(this._displays[idx], 1) - dateMenuButton.dateMenuFormatterDisplay = this._displays[idx] - } - if (panel.statusArea.dateMenu._clockDisplay.get_parent()) { - dateMenuButton.remove_child(panel.statusArea.dateMenu._clockDisplay) - } - }) - } - - _disableOn(panels) { - panels.forEach((panel) => { - const dateMenuButton = _getDateMenuButton(panel) - if (!panel.statusArea.dateMenu._clockDisplay.get_parent()) { - dateMenuButton.insert_child_at_index( - panel.statusArea.dateMenu._clockDisplay, - 1 - ) - } - if ( - dateMenuButton.dateMenuFormatterDisplay && - dateMenuButton.dateMenuFormatterDisplay.get_parent() - ) { - dateMenuButton.remove_child(dateMenuButton.dateMenuFormatterDisplay) - } - }) - } - - _onSettingsChange() { - this._fetchSettings() - // does Dash to Panel support more than 2 panels? better to be safe than sorry - if ( - global.dashToPanel && - this._displays.length < global.dashToPanel.panels.length - ) { - const missingPanels = - global.dashToPanel.panels.length - this._displays.length - this._displays = [ - ...this._displays, - ...Array.from({ length: missingPanels }, () => this._createDisplay()), - ] - } - - const [affectedPanels, unaffectedPanels] = this._getPanels() - if (REMOVE_MESSAGES_INDICATOR) { - this._removeIndicator(affectedPanels) - this._restoreIndicator(unaffectedPanels) - } else { - this._restoreIndicator([...affectedPanels, ...unaffectedPanels]) - } - this._enableOn(affectedPanels) - this._disableOn(unaffectedPanels) - this._displays.forEach( - (display) => - (display.style = `font-size: ${FONT_SIZE}pt; text-align: ${TEXT_ALIGN_MODE}`) - ) - } - - enable() { - EVERY = updateLevel() - this.formatters = new FormatterManager() - this._formatters_load_promise = this.formatters.loadFormatters() - this._displays = [this._createDisplay()] - if (global.dashToPanel) { - this._dashToPanelConnection = global.dashToPanel.connect( - 'panels-created', - () => this._onSettingsChange() - ) - } - this._loadSettings() - const [affectedPanels, _] = this._getPanels() - this._enableOn(affectedPanels) - this.start() - } - start() { - this._update = true - this._timerId = GLib.timeout_add(EVERY.priority, EVERY.timeout, () => - this.update() - ) - this.update() - } - stop(force) { - if (force) { - GLib.Source.remove(this._timerId) - } else { - this._update = false - } - } - restart() { - this.stop(true) - this.start() - } - - update() { - const setText = (text) => - this._displays.forEach((display) => (display.text = text)) - try { - setText(this._formatter.format(PATTERN, new Date())) - } catch (e) { - // if there is an exception during formatting, use the default display's text - setText(MainPanel.statusArea.dateMenu._clockDisplay.text) - if (this._formatter !== null && this._formatter !== undefined) - console.log('DateMenuFormatter: ' + e.message) - } - return this._update - } - - disable() { - EVERY = null - const [affectedPanels, unaffectedPanels] = this._getPanels() - const allPanels = [...affectedPanels, ...unaffectedPanels] - this._disableOn(allPanels) - this._restoreIndicator(allPanels) - this.stop() - if (this._settingsChangedId) { - this._settings.disconnect(this._settingsChangedId) - this._settingsChangedId = null - } - if (this._dashToPanelConnection) { - global.dashToPanel.disconnect(this._dashToPanelConnection) - this._dashToPanelConnection = null - } - this._settings = null - this.formatters = null - this._formatter = null - this._formatters_load_promise = null - this.display?.forEach((d) => d?.destroy()) - this._displays = null - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/formatters/01_luxon.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/formatters/01_luxon.js deleted file mode 100644 index bf5eac3d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/formatters/01_luxon.js +++ /dev/null @@ -1,86 +0,0 @@ -import { DateTime } from '../lib/luxon.js' -import { createFormatter, FormatterHelp } from '../utils/formatter.js' - -export default class extends createFormatter('Luxon', '', { - customTimezone: true, - customLocale: true, - customCalendar: true, -}) { - config(timezone, locale, calendar) { - this._timezone = timezone - this._locale = locale - this._calendar = calendar - } - - format(pattern, date) { - return DateTime.fromJSDate(date) - .setZone(this._timezone) - .reconfigure({ - locale: this._locale, - outputCalendar: this._calendar, - }) - .toFormat(pattern.replaceAll('\\n', '\n')) - } -} - -export function help() { - return new FormatterHelp( - 'https://moment.github.io/luxon/#/formatting?id=table-of-tokens', - [ - ['y', 'year', '2023'], - ['yy', 'year (2 digits only)', '23'], - ['', '', ''], - ['M', 'month (numeric)', '4'], - ['MM', 'month (numeric, padded)', '04'], - ['MMM', 'month (short)', 'Apr'], - ['MMMM', 'month (full)', 'April'], - ['MMMMM', 'month (narrow)', 'A'], - ['', '', ''], - ['', '', ''], - ['', '', ''], - ['', '', ''], - ['kk', 'ISO week year', '14'], - ['kkkk', 'ISO week year (padded to 4)', '2014'], - ['W', 'ISO week number', '32'], - ['WW', 'ISO week number (padded to 2)', '32'], - ['', '', ''], - ['d', 'day of month', '7'], - ['dd', 'day of month (padded)', '07'], - ['o', 'day of year (unpadded)', '98'], - ['ooo', 'day of year (padded to 3)', '002'], - ['', '', ''], - ['s', 'second (unpadded)', '4'], - ['ss', 'second (padded to 2)', '04'], - ['', '', ''], - ["'text'", 'literal text', ''], - ], - [ - ['E', 'weekday (numeric)', '1-7'], - ['EEE', 'weekday (abbrev.)', 'Tue'], - ['EEEE', 'weekday (full)', 'Tuesday'], - ['EEEEE', 'weekday (narrow)', 'T'], - ['', '', ''], - ['h', 'hour', '1-12'], - ['hh', 'hour (padded)', '01-12'], - ['H', 'hour', '0-23'], - ['HH', 'hour (padded)', '00-23'], - ['a', 'AM-PM', ''], - ['', '', ''], - ['ii', 'Local week year', '14'], - ['iiii', 'Local week year (padded to 4)', '2014'], - ['n', 'Local week number', '32'], - ['nn', 'Local week number (padded to 2)', '32'], - ['', '', ''], - ['m', 'minute', '7'], - ['mm', 'minute (padded)', '07'], - ['', '', ''], - ['q', 'quarter', '3'], - ['qq', 'quarter (padded)', '03'], - ['', '', ''], - ['S', 'millisecond (unpadded)', '4'], - ['SSS', 'millisecond (padded to 3)', '004'], - ['', '', ''], - ['\\n', 'new line', ''], - ] - ) -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/formatters/02_original.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/formatters/02_original.js deleted file mode 100644 index 4bee77d3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/formatters/02_original.js +++ /dev/null @@ -1,68 +0,0 @@ -import { SimpleDateFormat } from '../lib/SimpleDateFormat.js' -import { createFormatter, FormatterHelp } from '../utils/formatter.js' - -function convertToPattern(str) { - return '#' + str.replace(/\\n/g, '\n').replace(/''/g, '>`<') -} - -function convertFromPattern(str) { - return str.replace(/>` DateTimeFormat - f = this.mkFmtFnDtf(pat); - } - fnCt[pat] = f; - } - return f; - } - - /** - * create instance of Intl.DateTimeFormat for given pattern - * @param {string} pat SDF pattern for formatting - * @return {Intl.DateTimeFormat} - */ - getDTF(pat) { - // prep options - var o = SimpleDateFormat.dtfOptions(pat); - // prep formatter to work with - if (this.utc) o['timeZone'] = 'UTC'; - return new Intl.DateTimeFormat(this.getLocales(o), o); - } - - /** - * prepare quick get/set function for date parts - * @private - */ - prepDateFns() { - var dpFn = this.$dpFn, utc = this.utc, dp = Date.prototype; - dateFnParts.forEach((part) => { - var fnPart = utc ? ('UTC' + part) : part; - dpFn['get' + part] = dp['get' + fnPart]; - dpFn['set' + part] = dp['set' + fnPart]; - }); - dpFn.getTimezoneOffset = dp.getTimezoneOffset; - } - - /** - * create formatting function for SDF pattern (not auto-format) - * @private - * @param {string} pat SDF pattern input - * @returns {?dateFmtFn} - */ - mkPatternFormatter(pat) { - var rx = /([a-zA-Z'])\1*/g, m, fmtParts = [], i0 = 0, fmtFn = null; - // eslint-disable-next-line no-cond-assign - while (m = rx.exec(pat)) { - // m: [pat1, sig] - var pat1 = m[0], sig = m[1], i = rx.lastIndex, l = pat1.length, i1 = i - l; - // "l" is deprecated - if (sig == 'l') continue; - // some formatters are autoformat only - if ('jJC'.indexOf(sig) >= 0) continue; - // let's get to work - if (i1 > i0) - fmtParts.push(pat.substring(i0, i1)); - if (sig == "'") { - if (l > 1) fmtParts.push(pat1.substr(0, l >> 1)); - if (l & 1) { - i1 = pat.indexOf("'", i); - if (i1 > 0) { - fmtParts.push(pat.substring(i, i1)); - rx.lastIndex = i = i1 + 1; - } - } - } else { // a SimpleDateFormat pattern specifier - var p1f = this.getFmtSdf1(pat1); - if (p1f) fmtParts.push(p1f); - } - i0 = i; - } - // and return a formatting function for all of this - if (fmtParts.length) { - if (fmtParts.length > 1) { - fmtFn = (d) => { - var s = ''; - fmtParts.forEach((x) => { - if (x instanceof Function) - x = x(d); // use sub-formatter - s += x; - }); - return s; - }; - } else { // length == 1 - fmtFn = fmtParts[0]; - } - } - return fmtFn; - } - - /** - * get formatter for single SimpleDateFormat specifier - * @private - * @param {string} pat1 - * @returns {dateFmtFn|string} - */ - getFmtSdf1(pat1) { - var fnCt = this.fmt1, fmtFn = fnCt[pat1]; - if (!fmtFn && !(pat1 in fnCt)) { - fmtFn = fnCt[pat1] = this.getFmt1Fn(pat1); - } - return fmtFn; - } - - /** - * get non-DTF formatter for single SDF pattern - * @private - * @param {string} pat1 - * @returns {dateFmtFn} - */ - getFmt1Fn(pat1) { - return this.mkFmtFnDtf(pat1, 1) || this.getPatFn(pat1); - } - - /** - * get pre-defined formatting function for pattern - * @private - * @param {string} pat1 - * @returns {dateFmtFn} - */ - getPatFn(pat1) { - var fn, utc = this.utc, sig = pat1[0]; - if (pat1.length > 5 && 'eEc'.indexOf(sig) >= 0) { - // weekday: 6-len e, E or c - var fShort = this.getFmt1Fn(pat1.substr(0,3)); - if (fShort(new Date()).length > 2) { - fn = (d) => fShort(d).substr(0,2); - } else { - fn = fShort; - } - } else { // length 1..5 (as usual) - var fnSdf = sdfFnPat[pat1]; - if (fnSdf) { - fn = (d) => fnSdf(d, pat1, utc); - } else { - fnSdf = sdfFnSig[sig]; - fn = fnSdf && ((d) => fnSdf(d, pat1, utc)); - } - } - return fn; - } - - /** - * get project locale to use with DateTimeFormat (BCP47 tag) - * @private - * @param {Object=} o options - may influence locale - * @returns {string} - */ - // eslint-disable-next-line no-unused-vars - getLocales(o) { - return this.locale || (typeof navigator != 'undefined' ? navigator.language : 'en-US'); - } - - /** - * create formatting function using an instance of {@see Intl.DateTimeFormat} for given pattern - * @private - * @param {string} pat SDF pattern for autoformat - * @param {?=} [f1=false] truthy: single pattern to generate formatter for? - * @returns {?dateFmtFn} - */ - mkFmtFnDtf(pat, f1) { - // prep options - var o = {}, utc = this.utc, sig = pat[0]; - if (f1) { - // len=6 only allowed for weekdays, do not use DTF for that - if (pat.length > 5 && sig != 'S' && sig != 'A') return null; - if (!SimpleDateFormat.sdf2dtfO(pat, o)) return null; - } else { - SimpleDateFormat.dtfOptions(pat, o); - } - // prep formatter to work with - if (utc) o['timeZone'] = 'UTC'; - var fn, dtf = new Intl.DateTimeFormat(this.getLocales(o), o); - if (f1) { // not auto-formatting - // some formatters need some more work... - var dayEraVtz = "vVzGabB".indexOf(sig) >= 0; // day period, era or verbose timezone - if (dayEraVtz) { - var part = sdfO[sig][0]; - if (hasF2P) { - if (part == 'period') part = 'dayperiod'; - /** @this {Intl.DateTimeFormat} */ - fn = function(part, d) { - var fParts = this.formatToParts(d), - r0 = fParts.find((pp) => pp['type'].toLowerCase() == part); - return r0 && r0['value']; - }.bind(dtf, part); - } else { // try to extract text from longer string - /** @this {Intl.DateTimeFormat} */ - fn = function(d) { - var v0 = this.format(d); - // replace: all digits followed by non-words chars and whitespace - return v0.replace(/\s*\d+[^\w\s]*/g, '').trim(); - }.bind(dtf); - } - } else { // check some numerics: hours, minutes or seconds - or years! - var showHours = 'hHkK'.indexOf(sig) >= 0; - // hour formatters are quite special - move out of here? - if (showHours) { - var fnGetHours = this.$dpFn.getHours; - fn = (d) => { - var h0 = fnGetHours.call(d); - // don't show 0 hours -> 12 or 24 - if ((!h0 || h0 == 0) && (sig == 'H' || sig == 'K')) h0 = 24; - // restrict to 12 hour time - if (h0 > 12 && (sig == 'h' || sig == 'K')) h0 -= 12; - if (h0 == 0 && (sig == 'h' || sig == 'K')) h0 = 12; - // ev. pad to 2 digits - return (''+h0).padStart(pat.length, '0'); - }; - } else if ('sm'.indexOf(sig) >= 0) { - // minutes and seconds should be numbers - check this - // internet explorer has a problem with minutes and seconds - // see https://github.com/Microsoft/ChakraCore/issues/1223 - if (isNaN(dtf.format(new Date()))) return null; - if (pat.length > 1) { - // 2-digit minutes or seconds - /** @this {Intl.DateTimeFormat} */ - fn = function(d) { - var v = +this.format(d); - return ((v < 10) ? '0' : '') + v; - }.bind(dtf); - } - } - else if (pat.length == 5 && (sig == 'y' || sig == 'Y')) { - // ??? use NumberFormat if negative years are fixed upstream ??? - /** @this {Intl.DateTimeFormat} */ - fn = function(d) { return this.format(d).padStart(5, '0'); }.bind(dtf); - } - } - } - return fn || dtf.format.bind(dtf); - } - - /** - * update DTF options for single SDF pattern (updateFmtOpts) - * @private - * @static - * @param {string} pat pattern - * @param {Object} o dtf options to construct - * @returns {Object} DTF options object (if pat was found) - */ - static sdf2dtfO(pat, o) { - // no DTF options for week - var sig = pat[0], noDtf = 'wW'.indexOf(sig) >= 0; - var pDef = !noDtf && sdfO[sig]; - if (pDef) { - var prop = pDef[0], offset = pDef[1], idx; - if (offset && offset instanceof Function) { - idx = offset(pat); - } else { - idx = pat.length - 1; - if (offset) idx += offset; - var min = pDef[2]; - if (min && idx < min) idx = min; - var max = pDef[3]; - if (max && idx > max) idx = max; - } - o[prop] = dtfStyles[idx]; - // not for iso8601 TZ - if (sig == 'x' || sig == 'X' || (sig == 'Z' && pat.length >= 3)) - return null; - // any preference regarding 12/24 hour clock found? - if (hasHC && "hHkK".indexOf(sig) >= 0) { - o['hourCycle'] = sdfO['hc'][sig]; - } else { - if (sdfO['hour12'].indexOf(sig) >= 0) - o['hour12'] = true; - else if (sdfO['no12h'].indexOf(sig) >= 0) - o['hour12'] = false; - } - // no period w/o hour - if (o['period'] && !o['hour']) - o['hour'] = 'numeric'; - } else o = null; - return o; - } - - /** - * get DTF options for auto-formatting - * @private - * @param {!string} pat input pattern - * @param {Object=} o options to update if given - * @returns {Object} options - */ - static dtfOptions(pat, o) { - if (!o) o = {}; - var oRx = /([a-zA-Z])\1*/g, m; - // eslint-disable-next-line no-cond-assign - while (m = oRx.exec(pat)) { // m: [pat1, sig] - SimpleDateFormat.sdf2dtfO(m[0], o); - } - // 'hour12' would overwrite 'hourCycle', remove if both defined - if (o['hourCycle'] && 'hour12' in o) { - delete o['hour12']; - } - return o; - } - -} -Intl.SimpleDateFormat = SimpleDateFormat; -/** - * formatter cache - * @private {Object} - */ -const formatters = {}; - -/** - * for easier documentation using google closure compiler - * @typedef {function(!Date):!string} - */ -// eslint-disable-next-line no-unused-vars -var dateFmtFn; - -/** - * helper data for {@see SimpleDateFormat#prepDateFns} - * @type {Array} - */ -const dateFnParts = ['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds']; - -// helper objects to decide on the right formatter -const dtfData = {}; -const dtfStyles = dtfData.styles = ['numeric', '2-digit', 'short', 'long', 'narrow'], - sdfO = dtfData.sig = {}, sdfFnSig = dtfData.sigFn = {}, sdfFnPat = dtfData.patFn = {}; -//--- era: G ------------------------------------------------------------ -sdfO['G'] = ['era', 0, 2]; -// year: yYuUr -sdfO['y'] = sdfO['Y'] = ['year', function(p) { return (p.length == 2) ? 1 : 0; }]; -sdfO['u'] = sdfO['r'] = ["year"]; -// ??? U: cyclic year name -> n/a -//--- quarter: Qq ------------------------------------------------------- -sdfFnSig['Q'] = sdfFnSig['q'] = function(d, pat, utc) { - var m = utc ? d.getUTCMonth() : d.getMonth(), q = 1 + ~~(m/3), s; - var pads = ['', '0', 'Q', null, ''], l = pat.length; - if (l == 4) { - s = q + '. quarter'; // TODO: localize / use ordinal suffix - } else { - s = pads[l-1] + q; - } - return s; -}; -//--- month: MLl -------------------------------------------------------- -sdfO['M'] = sdfO['L'] = ['month']; -// ??? l - deprecated -//--- week: wW ---------------------------------------------------------- -sdfO['w'] = ['week', 0, 0, 1]; -sdfFnSig['w'] = function weekNumYear(d, pat, utc) { // week of year - var firstWeekday = 'sunday', // or monday ? -> locale dependent! - weekday = utc ? d.getUTCDay() : d.getDay(); - // adjust weekday ??? - if (firstWeekday === 'monday') { - if (weekday === 0) // Sunday - weekday = 6; - else - weekday--; - } - - var d1 = utc ? new Date(Date.UTC(d.getUTCFullYear(), 0, 1)) : new Date(d.getFullYear(), 0, 1), - yday = Math.floor((d - d1) / 86400000), - weekNum = (yday + 7 - weekday) / 7; - return Math.floor(weekNum); -}; -// eslint-disable-next-line no-unused-vars -sdfFnSig['W'] = (d, pat, utc) => { // week of month - first dirty approx - return '?'; // better none than wrong, this needs locale data <- TODO !!! -}; -//--- day: dDFg --------------------------------------------------------- -sdfO['d'] = ['day', 0, 0, 1]; -// D - day of year (num) -> %j -// ??? F - day of week in month (num), ie: "2" for "2nd Wed in July" -sdfFnSig['F'] = (d, pat, utc) => { - var dm = utc ? d.getUTCDate() : d.getDate(); - return '' + (1 + ~~((dm-1)/7)); -}; -// g - modified julian day (num) -sdfFnSig['g'] = (d, pat, utc) => { - var d0 = (+d / 86400000); - if (!utc) d0 -= (d.getTimezoneOffset() / 1440); - return '' + ~~(d0 + 2440587.5); -}; -//--- weekday: Eec ------------------------------------------------------ -sdfO['E'] = ['weekday', 0, 2, 4]; -sdfO['e'] = sdfO['c'] = ['weekday', 0, 2, 5]; // TODO: 'numeric' and '2-digit' not valid here ??? -// c, cc, e -> numeric: 1 digit -sdfFnPat['c'] = sdfFnPat['cc'] = sdfFnPat['e'] = (d, pat1, utc) => { - return '' + ((utc ? d.getUTCDay() : d.getDay()) || 7); -}; -// ee -> numeric: 2 digits (0pad) -sdfFnPat['ee'] = (d, pat1, utc) => { - return '0' + ((utc ? d.getUTCDay() : d.getDay()) || 7); -}; -//--- period: abB ------------------------------------------------------- -sdfO['a'] = sdfO['b'] = sdfO['B'] = ['period']; -//--- hour: hHKkjJC ----------------------------------------------------- -sdfO['h'] = sdfO['H'] = sdfO['k'] = sdfO['K'] = sdfO['j'] = sdfO['J'] = sdfO['C'] = ['hour', 0, 0, 1]; -//--- minute: m --------------------------------------------------------- -sdfO['m'] = ['minute', 0, 0, 1]; -//--- second: sSA ------------------------------------------------------- -sdfO['s'] = ['second', 0, 0, 1]; -// eslint-disable-next-line no-unused-vars -sdfFnSig['S'] = (d, pat, utc) => { // fractional second - var ms1 = 1000 + d.getMilliseconds(), l = pat.length, s0 = '' + ms1; - if (l > 3) s0 = s0.padEnd(l+1, '0'); - return s0.substr(1, l); -}; -sdfFnSig['A'] = (d, pat, utc) => { // milliseconds in day - var ms = +d; - if (utc) ms -= (d.getTimezoneOffset() * 60000); // TZ offset: minutes -> ms - return ('' + (ms % 86400000)).padStart(pat.length, '0'); -}; -// sep ??? -//--- zone: zZOvVXx ----------------------------------------------------- -const iso8601tz = (d, utc, opts) => { - var tzo = utc ? 0 : d.getTimezoneOffset(), res = ''; - if (opts.z0 && !tzo) return 'Z'; - if (opts.gmt) { - res = 'GMT'; - if (!tzo) return res; - } - // add sign and hours - res += (tzo > 0) ? '-' : '+'; // strange: tzo < 0 -> GMT+xxx - if (tzo < 0) // sign handled, make calc easier - tzo = -tzo; - var h = ~~(tzo/60), m = 0, s = 0; - res += ((opts.h2 && h < 10) ? '0' : '') + h; // hours - // minutes - m = tzo % 60; - s = ~~(m * 60); - if (!opts.noM0 || m || s) { - if (opts.sep) res += ':'; - res += ((m < 10) ? '0' : '') + m; - if (opts.secs) { - if (s) { - if (opts.sep) res += ':'; - res += ((s < 10) ? '0' : '') + s; - } - } - } - return res; -}; -sdfO['z'] = sdfO['Z'] = sdfO['v'] = ['timeZoneName', 0, 2, 3]; -sdfFnSig['Z'] = (d, pat, utc) => { - var pl = pat.length, l4 = pl == 4; - var opts = {gmt:l4, h2:!l4, sep: pl>=4, secs: pl>=5, z0: pl>=5}; - return iso8601tz(d, utc, opts); -}; -sdfFnSig['O'] = (d, pat, utc) => { - // all length but 1 and 4 should be an error - var pl = pat.length, opts = {gmt:true, h2: pl>=3, noM0: pl<3, sep:pl>=3}; - return iso8601tz(d, utc, opts); -}; -sdfO['V'] = ['timeZoneName', 0, 3, 3]; // always "long" -sdfO['X'] = sdfO['x'] = ['timeZoneName', 0, 2, 2]; // always "short" -sdfFnSig['X'] = sdfFnSig['x'] = (d, pat, utc) => { - var pl = pat.length, opts = { - h2: true, sep: pl>1 && pl&1, noM0: pl==1, secs: pl >= 4, z0: pat[0] == 'X' - }; - return iso8601tz(d, utc, opts); -}; -//----------------------------------------------------------------------- -// which formats suggest 12 hour clock? -sdfO['hour12'] = 'abBhK'; -// and which one don't want one? -sdfO['no12h'] = 'Hk'; -// hour cycles - K:h11 h:h12 H:h23 k:h24 -sdfO['hc'] = {"K":"h11", "h":"h12", "H":"h23", "k":"h24"}; - -let testF = new Intl.DateTimeFormat('en', {'hour':'numeric','hourCycle':'h23'}); -const hasF2P = !!testF['formatToParts']; -const hasHC = testF.resolvedOptions()['hourCycle'] == 'h23'; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/lib/importDir.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/lib/importDir.js deleted file mode 100644 index 00844c2e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/lib/importDir.js +++ /dev/null @@ -1,137 +0,0 @@ -import Gio from 'gi://Gio' - -function asGioPromise(obj, methodStart, methodFinish = undefined) { - methodFinish = - methodFinish ?? - methodStart.replace('_async', '').replace('_begin', '') + '_finish' - return function (...args) { - return new Promise((resolve, reject) => { - let { stack: callStack } = new Error() - this[methodStart](...args, function (source, res) { - try { - const result = - source !== null && source[methodFinish] !== undefined - ? source[methodFinish](res) - : obj[methodFinish](res) - if (Array.isArray(result) && result.length > 1 && result[0] === true) - result.shift() - resolve(result) - } catch (error) { - callStack = callStack - .split('\n') - .filter((line) => line.indexOf('_promisify/') === -1) - .join('\n') - if (error.stack) - error.stack += `### Promise created here: ###\n${callStack}` - else error.stack = callStack - reject(error) - } - }) - }) - }.bind(obj) -} - -const URI_SCHEMAS = Gio.Vfs.get_local() - .get_supported_uri_schemes() - .map((schema) => `${schema}://`) - -export function isUri(uri) { - const regex = /^([a-z]+:\/\/)/i - return regex.test(uri) -} -export function isSupportedUri(uri) { - for (const schema of URI_SCHEMAS) { - if (uri.startsWith(schema)) return true - } - return false -} - -function allowedExtension(name, extensions) { - for (const ext of extensions) { - if (name.endsWith(`.${ext}`)) return true - } - return false -} -function removeExtension(name, extensions) { - let fname = name - for (const ext of extensions) fname = fname.replaceAll(`.${ext}`, '') - return fname -} -async function children(directory) { - const ret = [] - const children = await asGioPromise(directory, 'enumerate_children_async')( - Gio.FILE_ATTRIBUTE_STANDARD_NAME, - Gio.FileQueryInfoFlags.NONE, - 0, - null - ) - let child = children.next_file(null) - while (child) { - ret.push({ - name: child.get_name(), - type: Object.keys(Gio.FileType)[child.get_file_type()], - }) - child = children.next_file(null) - } - return ret - .filter( - ({ type }) => - type !== Gio.FileType.REGULAR && type !== Gio.FileType.UNKNOWN - ) - .map((c) => c.name) -} - -export function resolveFile(uri, ...paths) { - //the code work for most cases - let file - if (isUri(uri)) { - file = Gio.File.new_for_uri(isSupportedUri(uri) ? uri : import.meta.url) - } else if (uri.startsWith('/')) { - file = Gio.File.new_for_path(uri) - } else { - file = Gio.File.new_for_uri(import.meta.url) - paths.push(uri) - } - const fileInfo = file.query_info( - Gio.FILE_ATTRIBUTE_STANDARD_NAME + ',' + Gio.FILE_ATTRIBUTE_STANDARD_TYPE, - Gio.FileQueryInfoFlags.NONE, - null - ) - if (fileInfo.get_file_type() === Gio.FileType.REGULAR) { - file = file.get_parent() - } - if (paths.length > 0) { - for (const path of paths) { - file = file.resolve_relative_path(path) - } - } - return file -} -export function resolvePath(...paths) { - const file = resolveFile(...paths) - return file.get_uri() === import.meta.url ? '' : file.get_path() -} -export function resolveUri(...paths) { - const file = resolveFile(...paths) - return file.get_uri() === import.meta.url ? '' : file.get_uri() -} - -export async function importDir( - dir, - excludeIndex = false, - enabledExtension = ['js', 'ts'] -) { - const res = {} - dir = Array.isArray(dir) ? dir : [dir] - const directory = resolveFile(...dir) - const files = await children(directory) - for (const file of files) { - if (allowedExtension(file, enabledExtension)) { - const name = removeExtension(file, enabledExtension) - if (!(excludeIndex && name.toLowerCase() === 'index')) { - res[name] = await import(`${directory.get_uri()}/${file}`) - } - } - } - return res -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/lib/luxon.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/lib/luxon.js deleted file mode 100644 index 34a3d7cc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/lib/luxon.js +++ /dev/null @@ -1,8139 +0,0 @@ -// these aren't really private, but nor are they really useful to document - -/** - * @private - */ -class LuxonError extends Error {} - -/** - * @private - */ -class InvalidDateTimeError extends LuxonError { - constructor(reason) { - super(`Invalid DateTime: ${reason.toMessage()}`) - } -} - -/** - * @private - */ -class InvalidIntervalError extends LuxonError { - constructor(reason) { - super(`Invalid Interval: ${reason.toMessage()}`) - } -} - -/** - * @private - */ -class InvalidDurationError extends LuxonError { - constructor(reason) { - super(`Invalid Duration: ${reason.toMessage()}`) - } -} - -/** - * @private - */ -class ConflictingSpecificationError extends LuxonError {} - -/** - * @private - */ -class InvalidUnitError extends LuxonError { - constructor(unit) { - super(`Invalid unit ${unit}`) - } -} - -/** - * @private - */ -class InvalidArgumentError extends LuxonError {} - -/** - * @private - */ -class ZoneIsAbstractError extends LuxonError { - constructor() { - super('Zone is an abstract class') - } -} - -/** - * @private - */ - -const n = 'numeric', - s = 'short', - l = 'long' - -const DATE_SHORT = { - year: n, - month: n, - day: n, -} - -const DATE_MED = { - year: n, - month: s, - day: n, -} - -const DATE_MED_WITH_WEEKDAY = { - year: n, - month: s, - day: n, - weekday: s, -} - -const DATE_FULL = { - year: n, - month: l, - day: n, -} - -const DATE_HUGE = { - year: n, - month: l, - day: n, - weekday: l, -} - -const TIME_SIMPLE = { - hour: n, - minute: n, -} - -const TIME_WITH_SECONDS = { - hour: n, - minute: n, - second: n, -} - -const TIME_WITH_SHORT_OFFSET = { - hour: n, - minute: n, - second: n, - timeZoneName: s, -} - -const TIME_WITH_LONG_OFFSET = { - hour: n, - minute: n, - second: n, - timeZoneName: l, -} - -const TIME_24_SIMPLE = { - hour: n, - minute: n, - hourCycle: 'h23', -} - -const TIME_24_WITH_SECONDS = { - hour: n, - minute: n, - second: n, - hourCycle: 'h23', -} - -const TIME_24_WITH_SHORT_OFFSET = { - hour: n, - minute: n, - second: n, - hourCycle: 'h23', - timeZoneName: s, -} - -const TIME_24_WITH_LONG_OFFSET = { - hour: n, - minute: n, - second: n, - hourCycle: 'h23', - timeZoneName: l, -} - -const DATETIME_SHORT = { - year: n, - month: n, - day: n, - hour: n, - minute: n, -} - -const DATETIME_SHORT_WITH_SECONDS = { - year: n, - month: n, - day: n, - hour: n, - minute: n, - second: n, -} - -const DATETIME_MED = { - year: n, - month: s, - day: n, - hour: n, - minute: n, -} - -const DATETIME_MED_WITH_SECONDS = { - year: n, - month: s, - day: n, - hour: n, - minute: n, - second: n, -} - -const DATETIME_MED_WITH_WEEKDAY = { - year: n, - month: s, - day: n, - weekday: s, - hour: n, - minute: n, -} - -const DATETIME_FULL = { - year: n, - month: l, - day: n, - hour: n, - minute: n, - timeZoneName: s, -} - -const DATETIME_FULL_WITH_SECONDS = { - year: n, - month: l, - day: n, - hour: n, - minute: n, - second: n, - timeZoneName: s, -} - -const DATETIME_HUGE = { - year: n, - month: l, - day: n, - weekday: l, - hour: n, - minute: n, - timeZoneName: l, -} - -const DATETIME_HUGE_WITH_SECONDS = { - year: n, - month: l, - day: n, - weekday: l, - hour: n, - minute: n, - second: n, - timeZoneName: l, -} - -/** - * @interface - */ -class Zone { - /** - * The type of zone - * @abstract - * @type {string} - */ - get type() { - throw new ZoneIsAbstractError() - } - - /** - * The name of this zone. - * @abstract - * @type {string} - */ - get name() { - throw new ZoneIsAbstractError() - } - - get ianaName() { - return this.name - } - - /** - * Returns whether the offset is known to be fixed for the whole year. - * @abstract - * @type {boolean} - */ - get isUniversal() { - throw new ZoneIsAbstractError() - } - - /** - * Returns the offset's common name (such as EST) at the specified timestamp - * @abstract - * @param {number} ts - Epoch milliseconds for which to get the name - * @param {Object} opts - Options to affect the format - * @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'. - * @param {string} opts.locale - What locale to return the offset name in. - * @return {string} - */ - offsetName(ts, opts) { - throw new ZoneIsAbstractError() - } - - /** - * Returns the offset's value as a string - * @abstract - * @param {number} ts - Epoch milliseconds for which to get the offset - * @param {string} format - What style of offset to return. - * Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively - * @return {string} - */ - formatOffset(ts, format) { - throw new ZoneIsAbstractError() - } - - /** - * Return the offset in minutes for this zone at the specified timestamp. - * @abstract - * @param {number} ts - Epoch milliseconds for which to compute the offset - * @return {number} - */ - offset(ts) { - throw new ZoneIsAbstractError() - } - - /** - * Return whether this Zone is equal to another zone - * @abstract - * @param {Zone} otherZone - the zone to compare - * @return {boolean} - */ - equals(otherZone) { - throw new ZoneIsAbstractError() - } - - /** - * Return whether this Zone is valid. - * @abstract - * @type {boolean} - */ - get isValid() { - throw new ZoneIsAbstractError() - } -} - -let singleton$1 = null - -/** - * Represents the local zone for this JavaScript environment. - * @implements {Zone} - */ -class SystemZone extends Zone { - /** - * Get a singleton instance of the local zone - * @return {SystemZone} - */ - static get instance() { - if (singleton$1 === null) { - singleton$1 = new SystemZone() - } - return singleton$1 - } - - /** @override **/ - get type() { - return 'system' - } - - /** @override **/ - get name() { - return new Intl.DateTimeFormat().resolvedOptions().timeZone - } - - /** @override **/ - get isUniversal() { - return false - } - - /** @override **/ - offsetName(ts, { format, locale }) { - return parseZoneInfo(ts, format, locale) - } - - /** @override **/ - formatOffset(ts, format) { - return formatOffset(this.offset(ts), format) - } - - /** @override **/ - offset(ts) { - return -new Date(ts).getTimezoneOffset() - } - - /** @override **/ - equals(otherZone) { - return otherZone.type === 'system' - } - - /** @override **/ - get isValid() { - return true - } -} - -let dtfCache = {} -function makeDTF(zone) { - if (!dtfCache[zone]) { - dtfCache[zone] = new Intl.DateTimeFormat('en-US', { - hour12: false, - timeZone: zone, - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - era: 'short', - }) - } - return dtfCache[zone] -} - -const typeToPos = { - year: 0, - month: 1, - day: 2, - era: 3, - hour: 4, - minute: 5, - second: 6, -} - -function hackyOffset(dtf, date) { - const formatted = dtf.format(date).replace(/\u200E/g, ''), - parsed = /(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted), - [, fMonth, fDay, fYear, fadOrBc, fHour, fMinute, fSecond] = parsed - return [fYear, fMonth, fDay, fadOrBc, fHour, fMinute, fSecond] -} - -function partsOffset(dtf, date) { - const formatted = dtf.formatToParts(date) - const filled = [] - for (let i = 0; i < formatted.length; i++) { - const { type, value } = formatted[i] - const pos = typeToPos[type] - - if (type === 'era') { - filled[pos] = value - } else if (!isUndefined(pos)) { - filled[pos] = parseInt(value, 10) - } - } - return filled -} - -let ianaZoneCache = {} -/** - * A zone identified by an IANA identifier, like America/New_York - * @implements {Zone} - */ -class IANAZone extends Zone { - /** - * @param {string} name - Zone name - * @return {IANAZone} - */ - static create(name) { - if (!ianaZoneCache[name]) { - ianaZoneCache[name] = new IANAZone(name) - } - return ianaZoneCache[name] - } - - /** - * Reset local caches. Should only be necessary in testing scenarios. - * @return {void} - */ - static resetCache() { - ianaZoneCache = {} - dtfCache = {} - } - - /** - * Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that. - * @param {string} s - The string to check validity on - * @example IANAZone.isValidSpecifier("America/New_York") //=> true - * @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false - * @deprecated This method returns false for some valid IANA names. Use isValidZone instead. - * @return {boolean} - */ - static isValidSpecifier(s) { - return this.isValidZone(s) - } - - /** - * Returns whether the provided string identifies a real zone - * @param {string} zone - The string to check - * @example IANAZone.isValidZone("America/New_York") //=> true - * @example IANAZone.isValidZone("Fantasia/Castle") //=> false - * @example IANAZone.isValidZone("Sport~~blorp") //=> false - * @return {boolean} - */ - static isValidZone(zone) { - if (!zone) { - return false - } - try { - new Intl.DateTimeFormat('en-US', { timeZone: zone }).format() - return true - } catch (e) { - return false - } - } - - constructor(name) { - super() - /** @private **/ - this.zoneName = name - /** @private **/ - this.valid = IANAZone.isValidZone(name) - } - - /** @override **/ - get type() { - return 'iana' - } - - /** @override **/ - get name() { - return this.zoneName - } - - /** @override **/ - get isUniversal() { - return false - } - - /** @override **/ - offsetName(ts, { format, locale }) { - return parseZoneInfo(ts, format, locale, this.name) - } - - /** @override **/ - formatOffset(ts, format) { - return formatOffset(this.offset(ts), format) - } - - /** @override **/ - offset(ts) { - const date = new Date(ts) - - if (isNaN(date)) return NaN - - const dtf = makeDTF(this.name) - let [year, month, day, adOrBc, hour, minute, second] = dtf.formatToParts - ? partsOffset(dtf, date) - : hackyOffset(dtf, date) - - if (adOrBc === 'BC') { - year = -Math.abs(year) + 1 - } - - // because we're using hour12 and https://bugs.chromium.org/p/chromium/issues/detail?id=1025564&can=2&q=%2224%3A00%22%20datetimeformat - const adjustedHour = hour === 24 ? 0 : hour - - const asUTC = objToLocalTS({ - year, - month, - day, - hour: adjustedHour, - minute, - second, - millisecond: 0, - }) - - let asTS = +date - const over = asTS % 1000 - asTS -= over >= 0 ? over : 1000 + over - return (asUTC - asTS) / (60 * 1000) - } - - /** @override **/ - equals(otherZone) { - return otherZone.type === 'iana' && otherZone.name === this.name - } - - /** @override **/ - get isValid() { - return this.valid - } -} - -// todo - remap caching - -let intlLFCache = {} -function getCachedLF(locString, opts = {}) { - const key = JSON.stringify([locString, opts]) - let dtf = intlLFCache[key] - if (!dtf) { - dtf = new Intl.ListFormat(locString, opts) - intlLFCache[key] = dtf - } - return dtf -} - -let intlDTCache = {} -function getCachedDTF(locString, opts = {}) { - const key = JSON.stringify([locString, opts]) - let dtf = intlDTCache[key] - if (!dtf) { - dtf = new Intl.DateTimeFormat(locString, opts) - intlDTCache[key] = dtf - } - return dtf -} - -let intlNumCache = {} -function getCachedINF(locString, opts = {}) { - const key = JSON.stringify([locString, opts]) - let inf = intlNumCache[key] - if (!inf) { - inf = new Intl.NumberFormat(locString, opts) - intlNumCache[key] = inf - } - return inf -} - -let intlRelCache = {} -function getCachedRTF(locString, opts = {}) { - const { base, ...cacheKeyOpts } = opts // exclude `base` from the options - const key = JSON.stringify([locString, cacheKeyOpts]) - let inf = intlRelCache[key] - if (!inf) { - inf = new Intl.RelativeTimeFormat(locString, opts) - intlRelCache[key] = inf - } - return inf -} - -let sysLocaleCache = null -function systemLocale() { - if (sysLocaleCache) { - return sysLocaleCache - } else { - sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale - return sysLocaleCache - } -} - -let weekInfoCache = {} -function getCachedWeekInfo(locString) { - let data = weekInfoCache[locString] - if (!data) { - const locale = new Intl.Locale(locString) - // browsers currently implement this as a property, but spec says it should be a getter function - data = 'getWeekInfo' in locale ? locale.getWeekInfo() : locale.weekInfo - weekInfoCache[locString] = data - } - return data -} - -function parseLocaleString(localeStr) { - // I really want to avoid writing a BCP 47 parser - // see, e.g. https://github.com/wooorm/bcp-47 - // Instead, we'll do this: - - // a) if the string has no -u extensions, just leave it alone - // b) if it does, use Intl to resolve everything - // c) if Intl fails, try again without the -u - - // private subtags and unicode subtags have ordering requirements, - // and we're not properly parsing this, so just strip out the - // private ones if they exist. - const xIndex = localeStr.indexOf('-x-') - if (xIndex !== -1) { - localeStr = localeStr.substring(0, xIndex) - } - - const uIndex = localeStr.indexOf('-u-') - if (uIndex === -1) { - return [localeStr] - } else { - let options - let selectedStr - try { - options = getCachedDTF(localeStr).resolvedOptions() - selectedStr = localeStr - } catch (e) { - const smaller = localeStr.substring(0, uIndex) - options = getCachedDTF(smaller).resolvedOptions() - selectedStr = smaller - } - - const { numberingSystem, calendar } = options - return [selectedStr, numberingSystem, calendar] - } -} - -function intlConfigString(localeStr, numberingSystem, outputCalendar) { - if (outputCalendar || numberingSystem) { - if (!localeStr.includes('-u-')) { - localeStr += '-u' - } - - if (outputCalendar) { - localeStr += `-ca-${outputCalendar}` - } - - if (numberingSystem) { - localeStr += `-nu-${numberingSystem}` - } - return localeStr - } else { - return localeStr - } -} - -function mapMonths(f) { - const ms = [] - for (let i = 1; i <= 12; i++) { - const dt = DateTime.utc(2009, i, 1) - ms.push(f(dt)) - } - return ms -} - -function mapWeekdays(f) { - const ms = [] - for (let i = 1; i <= 7; i++) { - const dt = DateTime.utc(2016, 11, 13 + i) - ms.push(f(dt)) - } - return ms -} - -function listStuff(loc, length, englishFn, intlFn) { - const mode = loc.listingMode() - - if (mode === 'error') { - return null - } else if (mode === 'en') { - return englishFn(length) - } else { - return intlFn(length) - } -} - -function supportsFastNumbers(loc) { - if (loc.numberingSystem && loc.numberingSystem !== 'latn') { - return false - } else { - return ( - loc.numberingSystem === 'latn' || - !loc.locale || - loc.locale.startsWith('en') || - new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === - 'latn' - ) - } -} - -/** - * @private - */ - -class PolyNumberFormatter { - constructor(intl, forceSimple, opts) { - this.padTo = opts.padTo || 0 - this.floor = opts.floor || false - - const { padTo, floor, ...otherOpts } = opts - - if (!forceSimple || Object.keys(otherOpts).length > 0) { - const intlOpts = { useGrouping: false, ...opts } - if (opts.padTo > 0) intlOpts.minimumIntegerDigits = opts.padTo - this.inf = getCachedINF(intl, intlOpts) - } - } - - format(i) { - if (this.inf) { - const fixed = this.floor ? Math.floor(i) : i - return this.inf.format(fixed) - } else { - // to match the browser's numberformatter defaults - const fixed = this.floor ? Math.floor(i) : roundTo(i, 3) - return padStart(fixed, this.padTo) - } - } -} - -/** - * @private - */ - -class PolyDateFormatter { - constructor(dt, intl, opts) { - this.opts = opts - this.originalZone = undefined - - let z = undefined - if (this.opts.timeZone) { - // Don't apply any workarounds if a timeZone is explicitly provided in opts - this.dt = dt - } else if (dt.zone.type === 'fixed') { - // UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like. - // That is why fixed-offset TZ is set to that unless it is: - // 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT. - // 2. Unsupported by the browser: - // - some do not support Etc/ - // - < Etc/GMT-14, > Etc/GMT+12, and 30-minute or 45-minute offsets are not part of tzdata - const gmtOffset = -1 * (dt.offset / 60) - const offsetZ = - gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}` - if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) { - z = offsetZ - this.dt = dt - } else { - // Not all fixed-offset zones like Etc/+4:30 are present in tzdata so - // we manually apply the offset and substitute the zone as needed. - z = 'UTC' - this.dt = - dt.offset === 0 ? dt : dt.setZone('UTC').plus({ minutes: dt.offset }) - this.originalZone = dt.zone - } - } else if (dt.zone.type === 'system') { - this.dt = dt - } else if (dt.zone.type === 'iana') { - this.dt = dt - z = dt.zone.name - } else { - // Custom zones can have any offset / offsetName so we just manually - // apply the offset and substitute the zone as needed. - z = 'UTC' - this.dt = dt.setZone('UTC').plus({ minutes: dt.offset }) - this.originalZone = dt.zone - } - - const intlOpts = { ...this.opts } - intlOpts.timeZone = intlOpts.timeZone || z - this.dtf = getCachedDTF(intl, intlOpts) - } - - format() { - if (this.originalZone) { - // If we have to substitute in the actual zone name, we have to use - // formatToParts so that the timezone can be replaced. - return this.formatToParts() - .map(({ value }) => value) - .join('') - } - return this.dtf.format(this.dt.toJSDate()) - } - - formatToParts() { - const parts = this.dtf.formatToParts(this.dt.toJSDate()) - if (this.originalZone) { - return parts.map((part) => { - if (part.type === 'timeZoneName') { - const offsetName = this.originalZone.offsetName(this.dt.ts, { - locale: this.dt.locale, - format: this.opts.timeZoneName, - }) - return { - ...part, - value: offsetName, - } - } else { - return part - } - }) - } - return parts - } - - resolvedOptions() { - return this.dtf.resolvedOptions() - } -} - -/** - * @private - */ -class PolyRelFormatter { - constructor(intl, isEnglish, opts) { - this.opts = { style: 'long', ...opts } - if (!isEnglish && hasRelative()) { - this.rtf = getCachedRTF(intl, opts) - } - } - - format(count, unit) { - if (this.rtf) { - return this.rtf.format(count, unit) - } else { - return formatRelativeTime( - unit, - count, - this.opts.numeric, - this.opts.style !== 'long' - ) - } - } - - formatToParts(count, unit) { - if (this.rtf) { - return this.rtf.formatToParts(count, unit) - } else { - return [] - } - } -} - -const fallbackWeekSettings = { - firstDay: 1, - minimalDays: 4, - weekend: [6, 7], -} - -/** - * @private - */ - -class Locale { - static fromOpts(opts) { - return Locale.create( - opts.locale, - opts.numberingSystem, - opts.outputCalendar, - opts.weekSettings, - opts.defaultToEN - ) - } - - static create( - locale, - numberingSystem, - outputCalendar, - weekSettings, - defaultToEN = false - ) { - const specifiedLocale = locale || Settings.defaultLocale - // the system locale is useful for human readable strings but annoying for parsing/formatting known formats - const localeR = specifiedLocale || (defaultToEN ? 'en-US' : systemLocale()) - const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem - const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar - const weekSettingsR = - validateWeekSettings(weekSettings) || Settings.defaultWeekSettings - return new Locale( - localeR, - numberingSystemR, - outputCalendarR, - weekSettingsR, - specifiedLocale - ) - } - - static resetCache() { - sysLocaleCache = null - intlDTCache = {} - intlNumCache = {} - intlRelCache = {} - } - - static fromObject({ - locale, - numberingSystem, - outputCalendar, - weekSettings, - } = {}) { - return Locale.create(locale, numberingSystem, outputCalendar, weekSettings) - } - - constructor( - locale, - numbering, - outputCalendar, - weekSettings, - specifiedLocale - ) { - const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = - parseLocaleString(locale) - - this.locale = parsedLocale - this.numberingSystem = numbering || parsedNumberingSystem || null - this.outputCalendar = outputCalendar || parsedOutputCalendar || null - this.weekSettings = weekSettings - this.intl = intlConfigString( - this.locale, - this.numberingSystem, - this.outputCalendar - ) - - this.weekdaysCache = { format: {}, standalone: {} } - this.monthsCache = { format: {}, standalone: {} } - this.meridiemCache = null - this.eraCache = {} - - this.specifiedLocale = specifiedLocale - this.fastNumbersCached = null - } - - get fastNumbers() { - if (this.fastNumbersCached == null) { - this.fastNumbersCached = supportsFastNumbers(this) - } - - return this.fastNumbersCached - } - - listingMode() { - const isActuallyEn = this.isEnglish() - const hasNoWeirdness = - (this.numberingSystem === null || this.numberingSystem === 'latn') && - (this.outputCalendar === null || this.outputCalendar === 'gregory') - return isActuallyEn && hasNoWeirdness ? 'en' : 'intl' - } - - clone(alts) { - if (!alts || Object.getOwnPropertyNames(alts).length === 0) { - return this - } else { - return Locale.create( - alts.locale || this.specifiedLocale, - alts.numberingSystem || this.numberingSystem, - alts.outputCalendar || this.outputCalendar, - validateWeekSettings(alts.weekSettings) || this.weekSettings, - alts.defaultToEN || false - ) - } - } - - redefaultToEN(alts = {}) { - return this.clone({ ...alts, defaultToEN: true }) - } - - redefaultToSystem(alts = {}) { - return this.clone({ ...alts, defaultToEN: false }) - } - - months(length, format = false) { - return listStuff(this, length, months, () => { - const intl = format - ? { month: length, day: 'numeric' } - : { month: length }, - formatStr = format ? 'format' : 'standalone' - if (!this.monthsCache[formatStr][length]) { - this.monthsCache[formatStr][length] = mapMonths((dt) => - this.extract(dt, intl, 'month') - ) - } - return this.monthsCache[formatStr][length] - }) - } - - weekdays(length, format = false) { - return listStuff(this, length, weekdays, () => { - const intl = format - ? { weekday: length, year: 'numeric', month: 'long', day: 'numeric' } - : { weekday: length }, - formatStr = format ? 'format' : 'standalone' - if (!this.weekdaysCache[formatStr][length]) { - this.weekdaysCache[formatStr][length] = mapWeekdays((dt) => - this.extract(dt, intl, 'weekday') - ) - } - return this.weekdaysCache[formatStr][length] - }) - } - - meridiems() { - return listStuff( - this, - undefined, - () => meridiems, - () => { - // In theory there could be aribitrary day periods. We're gonna assume there are exactly two - // for AM and PM. This is probably wrong, but it's makes parsing way easier. - if (!this.meridiemCache) { - const intl = { hour: 'numeric', hourCycle: 'h12' } - this.meridiemCache = [ - DateTime.utc(2016, 11, 13, 9), - DateTime.utc(2016, 11, 13, 19), - ].map((dt) => this.extract(dt, intl, 'dayperiod')) - } - - return this.meridiemCache - } - ) - } - - eras(length) { - return listStuff(this, length, eras, () => { - const intl = { era: length } - - // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates - // to definitely enumerate them. - if (!this.eraCache[length]) { - this.eraCache[length] = [ - DateTime.utc(-40, 1, 1), - DateTime.utc(2017, 1, 1), - ].map((dt) => this.extract(dt, intl, 'era')) - } - - return this.eraCache[length] - }) - } - - extract(dt, intlOpts, field) { - const df = this.dtFormatter(dt, intlOpts), - results = df.formatToParts(), - matching = results.find((m) => m.type.toLowerCase() === field) - return matching ? matching.value : null - } - - numberFormatter(opts = {}) { - // this forcesimple option is never used (the only caller short-circuits on it, but it seems safer to leave) - // (in contrast, the rest of the condition is used heavily) - return new PolyNumberFormatter( - this.intl, - opts.forceSimple || this.fastNumbers, - opts - ) - } - - dtFormatter(dt, intlOpts = {}) { - return new PolyDateFormatter(dt, this.intl, intlOpts) - } - - relFormatter(opts = {}) { - return new PolyRelFormatter(this.intl, this.isEnglish(), opts) - } - - listFormatter(opts = {}) { - return getCachedLF(this.intl, opts) - } - - isEnglish() { - return ( - this.locale === 'en' || - this.locale.toLowerCase() === 'en-us' || - new Intl.DateTimeFormat(this.intl) - .resolvedOptions() - .locale.startsWith('en-us') - ) - } - - getWeekSettings() { - if (this.weekSettings) { - return this.weekSettings - } else if (!hasLocaleWeekInfo()) { - return fallbackWeekSettings - } else { - return getCachedWeekInfo(this.locale) - } - } - - getStartOfWeek() { - return this.getWeekSettings().firstDay - } - - getMinDaysInFirstWeek() { - return this.getWeekSettings().minimalDays - } - - getWeekendDays() { - return this.getWeekSettings().weekend - } - - equals(other) { - return ( - this.locale === other.locale && - this.numberingSystem === other.numberingSystem && - this.outputCalendar === other.outputCalendar - ) - } -} - -let singleton = null - -/** - * A zone with a fixed offset (meaning no DST) - * @implements {Zone} - */ -class FixedOffsetZone extends Zone { - /** - * Get a singleton instance of UTC - * @return {FixedOffsetZone} - */ - static get utcInstance() { - if (singleton === null) { - singleton = new FixedOffsetZone(0) - } - return singleton - } - - /** - * Get an instance with a specified offset - * @param {number} offset - The offset in minutes - * @return {FixedOffsetZone} - */ - static instance(offset) { - return offset === 0 - ? FixedOffsetZone.utcInstance - : new FixedOffsetZone(offset) - } - - /** - * Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6" - * @param {string} s - The offset string to parse - * @example FixedOffsetZone.parseSpecifier("UTC+6") - * @example FixedOffsetZone.parseSpecifier("UTC+06") - * @example FixedOffsetZone.parseSpecifier("UTC-6:00") - * @return {FixedOffsetZone} - */ - static parseSpecifier(s) { - if (s) { - const r = s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i) - if (r) { - return new FixedOffsetZone(signedOffset(r[1], r[2])) - } - } - return null - } - - constructor(offset) { - super() - /** @private **/ - this.fixed = offset - } - - /** @override **/ - get type() { - return 'fixed' - } - - /** @override **/ - get name() { - return this.fixed === 0 ? 'UTC' : `UTC${formatOffset(this.fixed, 'narrow')}` - } - - get ianaName() { - if (this.fixed === 0) { - return 'Etc/UTC' - } else { - return `Etc/GMT${formatOffset(-this.fixed, 'narrow')}` - } - } - - /** @override **/ - offsetName() { - return this.name - } - - /** @override **/ - formatOffset(ts, format) { - return formatOffset(this.fixed, format) - } - - /** @override **/ - get isUniversal() { - return true - } - - /** @override **/ - offset() { - return this.fixed - } - - /** @override **/ - equals(otherZone) { - return otherZone.type === 'fixed' && otherZone.fixed === this.fixed - } - - /** @override **/ - get isValid() { - return true - } -} - -/** - * A zone that failed to parse. You should never need to instantiate this. - * @implements {Zone} - */ -class InvalidZone extends Zone { - constructor(zoneName) { - super() - /** @private */ - this.zoneName = zoneName - } - - /** @override **/ - get type() { - return 'invalid' - } - - /** @override **/ - get name() { - return this.zoneName - } - - /** @override **/ - get isUniversal() { - return false - } - - /** @override **/ - offsetName() { - return null - } - - /** @override **/ - formatOffset() { - return '' - } - - /** @override **/ - offset() { - return NaN - } - - /** @override **/ - equals() { - return false - } - - /** @override **/ - get isValid() { - return false - } -} - -/** - * @private - */ - -function normalizeZone(input, defaultZone) { - if (isUndefined(input) || input === null) { - return defaultZone - } else if (input instanceof Zone) { - return input - } else if (isString(input)) { - const lowered = input.toLowerCase() - if (lowered === 'default') return defaultZone - else if (lowered === 'local' || lowered === 'system') - return SystemZone.instance - else if (lowered === 'utc' || lowered === 'gmt') - return FixedOffsetZone.utcInstance - else - return FixedOffsetZone.parseSpecifier(lowered) || IANAZone.create(input) - } else if (isNumber(input)) { - return FixedOffsetZone.instance(input) - } else if ( - typeof input === 'object' && - 'offset' in input && - typeof input.offset === 'function' - ) { - // This is dumb, but the instanceof check above doesn't seem to really work - // so we're duck checking it - return input - } else { - return new InvalidZone(input) - } -} - -let now = () => Date.now(), - defaultZone = 'system', - defaultLocale = null, - defaultNumberingSystem = null, - defaultOutputCalendar = null, - twoDigitCutoffYear = 60, - throwOnInvalid, - defaultWeekSettings = null - -/** - * Settings contains static getters and setters that control Luxon's overall behavior. Luxon is a simple library with few options, but the ones it does have live here. - */ -class Settings { - /** - * Get the callback for returning the current timestamp. - * @type {function} - */ - static get now() { - return now - } - - /** - * Set the callback for returning the current timestamp. - * The function should return a number, which will be interpreted as an Epoch millisecond count - * @type {function} - * @example Settings.now = () => Date.now() + 3000 // pretend it is 3 seconds in the future - * @example Settings.now = () => 0 // always pretend it's Jan 1, 1970 at midnight in UTC time - */ - static set now(n) { - now = n - } - - /** - * Set the default time zone to create DateTimes in. Does not affect existing instances. - * Use the value "system" to reset this value to the system's time zone. - * @type {string} - */ - static set defaultZone(zone) { - defaultZone = zone - } - - /** - * Get the default time zone object currently used to create DateTimes. Does not affect existing instances. - * The default value is the system's time zone (the one set on the machine that runs this code). - * @type {Zone} - */ - static get defaultZone() { - return normalizeZone(defaultZone, SystemZone.instance) - } - - /** - * Get the default locale to create DateTimes with. Does not affect existing instances. - * @type {string} - */ - static get defaultLocale() { - return defaultLocale - } - - /** - * Set the default locale to create DateTimes with. Does not affect existing instances. - * @type {string} - */ - static set defaultLocale(locale) { - defaultLocale = locale - } - - /** - * Get the default numbering system to create DateTimes with. Does not affect existing instances. - * @type {string} - */ - static get defaultNumberingSystem() { - return defaultNumberingSystem - } - - /** - * Set the default numbering system to create DateTimes with. Does not affect existing instances. - * @type {string} - */ - static set defaultNumberingSystem(numberingSystem) { - defaultNumberingSystem = numberingSystem - } - - /** - * Get the default output calendar to create DateTimes with. Does not affect existing instances. - * @type {string} - */ - static get defaultOutputCalendar() { - return defaultOutputCalendar - } - - /** - * Set the default output calendar to create DateTimes with. Does not affect existing instances. - * @type {string} - */ - static set defaultOutputCalendar(outputCalendar) { - defaultOutputCalendar = outputCalendar - } - - /** - * @typedef {Object} WeekSettings - * @property {number} firstDay - * @property {number} minimalDays - * @property {number[]} weekend - */ - - /** - * @return {WeekSettings|null} - */ - static get defaultWeekSettings() { - return defaultWeekSettings - } - - /** - * Allows overriding the default locale week settings, i.e. the start of the week, the weekend and - * how many days are required in the first week of a year. - * Does not affect existing instances. - * - * @param {WeekSettings|null} weekSettings - */ - static set defaultWeekSettings(weekSettings) { - defaultWeekSettings = validateWeekSettings(weekSettings) - } - - /** - * Get the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century. - * @type {number} - */ - static get twoDigitCutoffYear() { - return twoDigitCutoffYear - } - - /** - * Set the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century. - * @type {number} - * @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpreted as current century - * @example Settings.twoDigitCutoffYear = 50 // '49' -> 1949; '50' -> 2050 - * @example Settings.twoDigitCutoffYear = 1950 // interpreted as 50 - * @example Settings.twoDigitCutoffYear = 2050 // ALSO interpreted as 50 - */ - static set twoDigitCutoffYear(cutoffYear) { - twoDigitCutoffYear = cutoffYear % 100 - } - - /** - * Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals - * @type {boolean} - */ - static get throwOnInvalid() { - return throwOnInvalid - } - - /** - * Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals - * @type {boolean} - */ - static set throwOnInvalid(t) { - throwOnInvalid = t - } - - /** - * Reset Luxon's global caches. Should only be necessary in testing scenarios. - * @return {void} - */ - static resetCaches() { - Locale.resetCache() - IANAZone.resetCache() - } -} - -class Invalid { - constructor(reason, explanation) { - this.reason = reason - this.explanation = explanation - } - - toMessage() { - if (this.explanation) { - return `${this.reason}: ${this.explanation}` - } else { - return this.reason - } - } -} - -const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], - leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335] - -function unitOutOfRange(unit, value) { - return new Invalid( - 'unit out of range', - `you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid` - ) -} - -function dayOfWeek(year, month, day) { - const d = new Date(Date.UTC(year, month - 1, day)) - - if (year < 100 && year >= 0) { - d.setUTCFullYear(d.getUTCFullYear() - 1900) - } - - const js = d.getUTCDay() - - return js === 0 ? 7 : js -} - -function computeOrdinal(year, month, day) { - return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1] -} - -function uncomputeOrdinal(year, ordinal) { - const table = isLeapYear(year) ? leapLadder : nonLeapLadder, - month0 = table.findIndex((i) => i < ordinal), - day = ordinal - table[month0] - return { month: month0 + 1, day } -} - -function isoWeekdayToLocal(isoWeekday, startOfWeek) { - return ((isoWeekday - startOfWeek + 7) % 7) + 1 -} - -/** - * @private - */ - -function gregorianToWeek(gregObj, minDaysInFirstWeek = 4, startOfWeek = 1) { - const { year, month, day } = gregObj, - ordinal = computeOrdinal(year, month, day), - weekday = isoWeekdayToLocal(dayOfWeek(year, month, day), startOfWeek) - - let weekNumber = Math.floor( - (ordinal - weekday + 14 - minDaysInFirstWeek) / 7 - ), - weekYear - - if (weekNumber < 1) { - weekYear = year - 1 - weekNumber = weeksInWeekYear(weekYear, minDaysInFirstWeek, startOfWeek) - } else if ( - weekNumber > weeksInWeekYear(year, minDaysInFirstWeek, startOfWeek) - ) { - weekYear = year + 1 - weekNumber = 1 - } else { - weekYear = year - } - - return { weekYear, weekNumber, weekday, ...timeObject(gregObj) } -} - -function weekToGregorian(weekData, minDaysInFirstWeek = 4, startOfWeek = 1) { - const { weekYear, weekNumber, weekday } = weekData, - weekdayOfJan4 = isoWeekdayToLocal( - dayOfWeek(weekYear, 1, minDaysInFirstWeek), - startOfWeek - ), - yearInDays = daysInYear(weekYear) - - let ordinal = - weekNumber * 7 + weekday - weekdayOfJan4 - 7 + minDaysInFirstWeek, - year - - if (ordinal < 1) { - year = weekYear - 1 - ordinal += daysInYear(year) - } else if (ordinal > yearInDays) { - year = weekYear + 1 - ordinal -= daysInYear(weekYear) - } else { - year = weekYear - } - - const { month, day } = uncomputeOrdinal(year, ordinal) - return { year, month, day, ...timeObject(weekData) } -} - -function gregorianToOrdinal(gregData) { - const { year, month, day } = gregData - const ordinal = computeOrdinal(year, month, day) - return { year, ordinal, ...timeObject(gregData) } -} - -function ordinalToGregorian(ordinalData) { - const { year, ordinal } = ordinalData - const { month, day } = uncomputeOrdinal(year, ordinal) - return { year, month, day, ...timeObject(ordinalData) } -} - -/** - * Check if local week units like localWeekday are used in obj. - * If so, validates that they are not mixed with ISO week units and then copies them to the normal week unit properties. - * Modifies obj in-place! - * @param obj the object values - */ -function usesLocalWeekValues(obj, loc) { - const hasLocaleWeekData = - !isUndefined(obj.localWeekday) || - !isUndefined(obj.localWeekNumber) || - !isUndefined(obj.localWeekYear) - if (hasLocaleWeekData) { - const hasIsoWeekData = - !isUndefined(obj.weekday) || - !isUndefined(obj.weekNumber) || - !isUndefined(obj.weekYear) - - if (hasIsoWeekData) { - throw new ConflictingSpecificationError( - 'Cannot mix locale-based week fields with ISO-based week fields' - ) - } - if (!isUndefined(obj.localWeekday)) obj.weekday = obj.localWeekday - if (!isUndefined(obj.localWeekNumber)) obj.weekNumber = obj.localWeekNumber - if (!isUndefined(obj.localWeekYear)) obj.weekYear = obj.localWeekYear - delete obj.localWeekday - delete obj.localWeekNumber - delete obj.localWeekYear - return { - minDaysInFirstWeek: loc.getMinDaysInFirstWeek(), - startOfWeek: loc.getStartOfWeek(), - } - } else { - return { minDaysInFirstWeek: 4, startOfWeek: 1 } - } -} - -function hasInvalidWeekData(obj, minDaysInFirstWeek = 4, startOfWeek = 1) { - const validYear = isInteger(obj.weekYear), - validWeek = integerBetween( - obj.weekNumber, - 1, - weeksInWeekYear(obj.weekYear, minDaysInFirstWeek, startOfWeek) - ), - validWeekday = integerBetween(obj.weekday, 1, 7) - - if (!validYear) { - return unitOutOfRange('weekYear', obj.weekYear) - } else if (!validWeek) { - return unitOutOfRange('week', obj.weekNumber) - } else if (!validWeekday) { - return unitOutOfRange('weekday', obj.weekday) - } else return false -} - -function hasInvalidOrdinalData(obj) { - const validYear = isInteger(obj.year), - validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year)) - - if (!validYear) { - return unitOutOfRange('year', obj.year) - } else if (!validOrdinal) { - return unitOutOfRange('ordinal', obj.ordinal) - } else return false -} - -function hasInvalidGregorianData(obj) { - const validYear = isInteger(obj.year), - validMonth = integerBetween(obj.month, 1, 12), - validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month)) - - if (!validYear) { - return unitOutOfRange('year', obj.year) - } else if (!validMonth) { - return unitOutOfRange('month', obj.month) - } else if (!validDay) { - return unitOutOfRange('day', obj.day) - } else return false -} - -function hasInvalidTimeData(obj) { - const { hour, minute, second, millisecond } = obj - const validHour = - integerBetween(hour, 0, 23) || - (hour === 24 && minute === 0 && second === 0 && millisecond === 0), - validMinute = integerBetween(minute, 0, 59), - validSecond = integerBetween(second, 0, 59), - validMillisecond = integerBetween(millisecond, 0, 999) - - if (!validHour) { - return unitOutOfRange('hour', hour) - } else if (!validMinute) { - return unitOutOfRange('minute', minute) - } else if (!validSecond) { - return unitOutOfRange('second', second) - } else if (!validMillisecond) { - return unitOutOfRange('millisecond', millisecond) - } else return false -} - -/* - This is just a junk drawer, containing anything used across multiple classes. - Because Luxon is small(ish), this should stay small and we won't worry about splitting - it up into, say, parsingUtil.js and basicUtil.js and so on. But they are divided up by feature area. -*/ - -/** - * @private - */ - -// TYPES - -function isUndefined(o) { - return typeof o === 'undefined' -} - -function isNumber(o) { - return typeof o === 'number' -} - -function isInteger(o) { - return typeof o === 'number' && o % 1 === 0 -} - -function isString(o) { - return typeof o === 'string' -} - -function isDate(o) { - return Object.prototype.toString.call(o) === '[object Date]' -} - -// CAPABILITIES - -function hasRelative() { - try { - return typeof Intl !== 'undefined' && !!Intl.RelativeTimeFormat - } catch (e) { - return false - } -} - -function hasLocaleWeekInfo() { - try { - return ( - typeof Intl !== 'undefined' && - !!Intl.Locale && - ('weekInfo' in Intl.Locale.prototype || - 'getWeekInfo' in Intl.Locale.prototype) - ) - } catch (e) { - return false - } -} - -// OBJECTS AND ARRAYS - -function maybeArray(thing) { - return Array.isArray(thing) ? thing : [thing] -} - -function bestBy(arr, by, compare) { - if (arr.length === 0) { - return undefined - } - return arr.reduce((best, next) => { - const pair = [by(next), next] - if (!best) { - return pair - } else if (compare(best[0], pair[0]) === best[0]) { - return best - } else { - return pair - } - }, null)[1] -} - -function pick(obj, keys) { - return keys.reduce((a, k) => { - a[k] = obj[k] - return a - }, {}) -} - -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop) -} - -function validateWeekSettings(settings) { - if (settings == null) { - return null - } else if (typeof settings !== 'object') { - throw new InvalidArgumentError('Week settings must be an object') - } else { - if ( - !integerBetween(settings.firstDay, 1, 7) || - !integerBetween(settings.minimalDays, 1, 7) || - !Array.isArray(settings.weekend) || - settings.weekend.some((v) => !integerBetween(v, 1, 7)) - ) { - throw new InvalidArgumentError('Invalid week settings') - } - return { - firstDay: settings.firstDay, - minimalDays: settings.minimalDays, - weekend: Array.from(settings.weekend), - } - } -} - -// NUMBERS AND STRINGS - -function integerBetween(thing, bottom, top) { - return isInteger(thing) && thing >= bottom && thing <= top -} - -// x % n but takes the sign of n instead of x -function floorMod(x, n) { - return x - n * Math.floor(x / n) -} - -function padStart(input, n = 2) { - const isNeg = input < 0 - let padded - if (isNeg) { - padded = '-' + ('' + -input).padStart(n, '0') - } else { - padded = ('' + input).padStart(n, '0') - } - return padded -} - -function parseInteger(string) { - if (isUndefined(string) || string === null || string === '') { - return undefined - } else { - return parseInt(string, 10) - } -} - -function parseFloating(string) { - if (isUndefined(string) || string === null || string === '') { - return undefined - } else { - return parseFloat(string) - } -} - -function parseMillis(fraction) { - // Return undefined (instead of 0) in these cases, where fraction is not set - if (isUndefined(fraction) || fraction === null || fraction === '') { - return undefined - } else { - const f = parseFloat('0.' + fraction) * 1000 - return Math.floor(f) - } -} - -function roundTo(number, digits, towardZero = false) { - const factor = 10 ** digits, - rounder = towardZero ? Math.trunc : Math.round - return rounder(number * factor) / factor -} - -// DATE BASICS - -function isLeapYear(year) { - return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) -} - -function daysInYear(year) { - return isLeapYear(year) ? 366 : 365 -} - -function daysInMonth(year, month) { - const modMonth = floorMod(month - 1, 12) + 1, - modYear = year + (month - modMonth) / 12 - - if (modMonth === 2) { - return isLeapYear(modYear) ? 29 : 28 - } else { - return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1] - } -} - -// convert a calendar object to a local timestamp (epoch, but with the offset baked in) -function objToLocalTS(obj) { - let d = Date.UTC( - obj.year, - obj.month - 1, - obj.day, - obj.hour, - obj.minute, - obj.second, - obj.millisecond - ) - - // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that - if (obj.year < 100 && obj.year >= 0) { - d = new Date(d) - // set the month and day again, this is necessary because year 2000 is a leap year, but year 100 is not - // so if obj.year is in 99, but obj.day makes it roll over into year 100, - // the calculations done by Date.UTC are using year 2000 - which is incorrect - d.setUTCFullYear(obj.year, obj.month - 1, obj.day) - } - return +d -} - -// adapted from moment.js: https://github.com/moment/moment/blob/000ac1800e620f770f4eb31b5ae908f6167b0ab2/src/lib/units/week-calendar-utils.js -function firstWeekOffset(year, minDaysInFirstWeek, startOfWeek) { - const fwdlw = isoWeekdayToLocal( - dayOfWeek(year, 1, minDaysInFirstWeek), - startOfWeek - ) - return -fwdlw + minDaysInFirstWeek - 1 -} - -function weeksInWeekYear(weekYear, minDaysInFirstWeek = 4, startOfWeek = 1) { - const weekOffset = firstWeekOffset(weekYear, minDaysInFirstWeek, startOfWeek) - const weekOffsetNext = firstWeekOffset( - weekYear + 1, - minDaysInFirstWeek, - startOfWeek - ) - return (daysInYear(weekYear) - weekOffset + weekOffsetNext) / 7 -} - -function untruncateYear(year) { - if (year > 99) { - return year - } else return year > Settings.twoDigitCutoffYear ? 1900 + year : 2000 + year -} - -// PARSING - -function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) { - const date = new Date(ts), - intlOpts = { - hourCycle: 'h23', - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - } - - if (timeZone) { - intlOpts.timeZone = timeZone - } - - const modified = { timeZoneName: offsetFormat, ...intlOpts } - - const parsed = new Intl.DateTimeFormat(locale, modified) - .formatToParts(date) - .find((m) => m.type.toLowerCase() === 'timezonename') - return parsed ? parsed.value : null -} - -// signedOffset('-5', '30') -> -330 -function signedOffset(offHourStr, offMinuteStr) { - let offHour = parseInt(offHourStr, 10) - - // don't || this because we want to preserve -0 - if (Number.isNaN(offHour)) { - offHour = 0 - } - - const offMin = parseInt(offMinuteStr, 10) || 0, - offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin - return offHour * 60 + offMinSigned -} - -// COERCION - -function asNumber(value) { - const numericValue = Number(value) - if (typeof value === 'boolean' || value === '' || Number.isNaN(numericValue)) - throw new InvalidArgumentError(`Invalid unit value ${value}`) - return numericValue -} - -function normalizeObject(obj, normalizer) { - const normalized = {} - for (const u in obj) { - if (hasOwnProperty(obj, u)) { - const v = obj[u] - if (v === undefined || v === null) continue - normalized[normalizer(u)] = asNumber(v) - } - } - return normalized -} - -function formatOffset(offset, format) { - const hours = Math.trunc(Math.abs(offset / 60)), - minutes = Math.trunc(Math.abs(offset % 60)), - sign = offset >= 0 ? '+' : '-' - - switch (format) { - case 'short': - return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}` - case 'narrow': - return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ''}` - case 'techie': - return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}` - default: - throw new RangeError( - `Value format ${format} is out of range for property format` - ) - } -} - -function timeObject(obj) { - return pick(obj, ['hour', 'minute', 'second', 'millisecond']) -} - -/** - * @private - */ - -const monthsLong = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', -] - -const monthsShort = [ - 'Jan', - 'Feb', - 'Mar', - 'Apr', - 'May', - 'Jun', - 'Jul', - 'Aug', - 'Sep', - 'Oct', - 'Nov', - 'Dec', -] - -const monthsNarrow = [ - 'J', - 'F', - 'M', - 'A', - 'M', - 'J', - 'J', - 'A', - 'S', - 'O', - 'N', - 'D', -] - -function months(length) { - switch (length) { - case 'narrow': - return [...monthsNarrow] - case 'short': - return [...monthsShort] - case 'long': - return [...monthsLong] - case 'numeric': - return ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] - case '2-digit': - return [ - '01', - '02', - '03', - '04', - '05', - '06', - '07', - '08', - '09', - '10', - '11', - '12', - ] - default: - return null - } -} - -const weekdaysLong = [ - 'Monday', - 'Tuesday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - 'Sunday', -] - -const weekdaysShort = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] - -const weekdaysNarrow = ['M', 'T', 'W', 'T', 'F', 'S', 'S'] - -function weekdays(length) { - switch (length) { - case 'narrow': - return [...weekdaysNarrow] - case 'short': - return [...weekdaysShort] - case 'long': - return [...weekdaysLong] - case 'numeric': - return ['1', '2', '3', '4', '5', '6', '7'] - default: - return null - } -} - -const meridiems = ['AM', 'PM'] - -const erasLong = ['Before Christ', 'Anno Domini'] - -const erasShort = ['BC', 'AD'] - -const erasNarrow = ['B', 'A'] - -function eras(length) { - switch (length) { - case 'narrow': - return [...erasNarrow] - case 'short': - return [...erasShort] - case 'long': - return [...erasLong] - default: - return null - } -} - -function meridiemForDateTime(dt) { - return meridiems[dt.hour < 12 ? 0 : 1] -} - -function weekdayForDateTime(dt, length) { - return weekdays(length)[dt.weekday - 1] -} - -function monthForDateTime(dt, length) { - return months(length)[dt.month - 1] -} - -function eraForDateTime(dt, length) { - return eras(length)[dt.year < 0 ? 0 : 1] -} - -function formatRelativeTime(unit, count, numeric = 'always', narrow = false) { - const units = { - years: ['year', 'yr.'], - quarters: ['quarter', 'qtr.'], - months: ['month', 'mo.'], - weeks: ['week', 'wk.'], - days: ['day', 'day', 'days'], - hours: ['hour', 'hr.'], - minutes: ['minute', 'min.'], - seconds: ['second', 'sec.'], - } - - const lastable = ['hours', 'minutes', 'seconds'].indexOf(unit) === -1 - - if (numeric === 'auto' && lastable) { - const isDay = unit === 'days' - switch (count) { - case 1: - return isDay ? 'tomorrow' : `next ${units[unit][0]}` - case -1: - return isDay ? 'yesterday' : `last ${units[unit][0]}` - case 0: - return isDay ? 'today' : `this ${units[unit][0]}` - } - } - - const isInPast = Object.is(count, -0) || count < 0, - fmtValue = Math.abs(count), - singular = fmtValue === 1, - lilUnits = units[unit], - fmtUnit = narrow - ? singular - ? lilUnits[1] - : lilUnits[2] || lilUnits[1] - : singular - ? units[unit][0] - : unit - return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}` -} - -function stringifyTokens(splits, tokenToString) { - let s = '' - for (const token of splits) { - if (token.literal) { - s += token.val - } else { - s += tokenToString(token.val) - } - } - return s -} - -const macroTokenToFormatOpts = { - D: DATE_SHORT, - DD: DATE_MED, - DDD: DATE_FULL, - DDDD: DATE_HUGE, - t: TIME_SIMPLE, - tt: TIME_WITH_SECONDS, - ttt: TIME_WITH_SHORT_OFFSET, - tttt: TIME_WITH_LONG_OFFSET, - T: TIME_24_SIMPLE, - TT: TIME_24_WITH_SECONDS, - TTT: TIME_24_WITH_SHORT_OFFSET, - TTTT: TIME_24_WITH_LONG_OFFSET, - f: DATETIME_SHORT, - ff: DATETIME_MED, - fff: DATETIME_FULL, - ffff: DATETIME_HUGE, - F: DATETIME_SHORT_WITH_SECONDS, - FF: DATETIME_MED_WITH_SECONDS, - FFF: DATETIME_FULL_WITH_SECONDS, - FFFF: DATETIME_HUGE_WITH_SECONDS, -} - -/** - * @private - */ - -class Formatter { - static create(locale, opts = {}) { - return new Formatter(locale, opts) - } - - static parseFormat(fmt) { - // white-space is always considered a literal in user-provided formats - // the " " token has a special meaning (see unitForToken) - - let current = null, - currentFull = '', - bracketed = false - const splits = [] - for (let i = 0; i < fmt.length; i++) { - const c = fmt.charAt(i) - if (c === "'") { - if (currentFull.length > 0) { - splits.push({ - literal: bracketed || /^\s+$/.test(currentFull), - val: currentFull, - }) - } - current = null - currentFull = '' - bracketed = !bracketed - } else if (bracketed) { - currentFull += c - } else if (c === current) { - currentFull += c - } else { - if (currentFull.length > 0) { - splits.push({ literal: /^\s+$/.test(currentFull), val: currentFull }) - } - currentFull = c - current = c - } - } - - if (currentFull.length > 0) { - splits.push({ - literal: bracketed || /^\s+$/.test(currentFull), - val: currentFull, - }) - } - - return splits - } - - static macroTokenToFormatOpts(token) { - return macroTokenToFormatOpts[token] - } - - constructor(locale, formatOpts) { - this.opts = formatOpts - this.loc = locale - this.systemLoc = null - } - - formatWithSystemDefault(dt, opts) { - if (this.systemLoc === null) { - this.systemLoc = this.loc.redefaultToSystem() - } - const df = this.systemLoc.dtFormatter(dt, { ...this.opts, ...opts }) - return df.format() - } - - dtFormatter(dt, opts = {}) { - return this.loc.dtFormatter(dt, { ...this.opts, ...opts }) - } - - formatDateTime(dt, opts) { - return this.dtFormatter(dt, opts).format() - } - - formatDateTimeParts(dt, opts) { - return this.dtFormatter(dt, opts).formatToParts() - } - - formatInterval(interval, opts) { - const df = this.dtFormatter(interval.start, opts) - return df.dtf.formatRange( - interval.start.toJSDate(), - interval.end.toJSDate() - ) - } - - resolvedOptions(dt, opts) { - return this.dtFormatter(dt, opts).resolvedOptions() - } - - num(n, p = 0) { - // we get some perf out of doing this here, annoyingly - if (this.opts.forceSimple) { - return padStart(n, p) - } - - const opts = { ...this.opts } - - if (p > 0) { - opts.padTo = p - } - - return this.loc.numberFormatter(opts).format(n) - } - - formatDateTimeFromString(dt, fmt) { - const knownEnglish = this.loc.listingMode() === 'en', - useDateTimeFormatter = - this.loc.outputCalendar && this.loc.outputCalendar !== 'gregory', - string = (opts, extract) => this.loc.extract(dt, opts, extract), - formatOffset = (opts) => { - if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) { - return 'Z' - } - - return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : '' - }, - meridiem = () => - knownEnglish - ? meridiemForDateTime(dt) - : string({ hour: 'numeric', hourCycle: 'h12' }, 'dayperiod'), - month = (length, standalone) => - knownEnglish - ? monthForDateTime(dt, length) - : string( - standalone - ? { month: length } - : { month: length, day: 'numeric' }, - 'month' - ), - weekday = (length, standalone) => - knownEnglish - ? weekdayForDateTime(dt, length) - : string( - standalone - ? { weekday: length } - : { weekday: length, month: 'long', day: 'numeric' }, - 'weekday' - ), - maybeMacro = (token) => { - const formatOpts = Formatter.macroTokenToFormatOpts(token) - if (formatOpts) { - return this.formatWithSystemDefault(dt, formatOpts) - } else { - return token - } - }, - era = (length) => - knownEnglish - ? eraForDateTime(dt, length) - : string({ era: length }, 'era'), - tokenToString = (token) => { - // Where possible: https://cldr.unicode.org/translation/date-time/date-time-symbols - switch (token) { - // ms - case 'S': - return this.num(dt.millisecond) - case 'u': - // falls through - case 'SSS': - return this.num(dt.millisecond, 3) - // seconds - case 's': - return this.num(dt.second) - case 'ss': - return this.num(dt.second, 2) - // fractional seconds - case 'uu': - return this.num(Math.floor(dt.millisecond / 10), 2) - case 'uuu': - return this.num(Math.floor(dt.millisecond / 100)) - // minutes - case 'm': - return this.num(dt.minute) - case 'mm': - return this.num(dt.minute, 2) - // hours - case 'h': - return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12) - case 'hh': - return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2) - case 'H': - return this.num(dt.hour) - case 'HH': - return this.num(dt.hour, 2) - // offset - case 'Z': - // like +6 - return formatOffset({ format: 'narrow', allowZ: this.opts.allowZ }) - case 'ZZ': - // like +06:00 - return formatOffset({ format: 'short', allowZ: this.opts.allowZ }) - case 'ZZZ': - // like +0600 - return formatOffset({ format: 'techie', allowZ: this.opts.allowZ }) - case 'ZZZZ': - // like EST - return dt.zone.offsetName(dt.ts, { - format: 'short', - locale: this.loc.locale, - }) - case 'ZZZZZ': - // like Eastern Standard Time - return dt.zone.offsetName(dt.ts, { - format: 'long', - locale: this.loc.locale, - }) - // zone - case 'z': - // like America/New_York - return dt.zoneName - // meridiems - case 'a': - return meridiem() - // dates - case 'd': - return useDateTimeFormatter - ? string({ day: 'numeric' }, 'day') - : this.num(dt.day) - case 'dd': - return useDateTimeFormatter - ? string({ day: '2-digit' }, 'day') - : this.num(dt.day, 2) - // weekdays - standalone - case 'c': - // like 1 - return this.num(dt.weekday) - case 'ccc': - // like 'Tues' - return weekday('short', true) - case 'cccc': - // like 'Tuesday' - return weekday('long', true) - case 'ccccc': - // like 'T' - return weekday('narrow', true) - // weekdays - format - case 'E': - // like 1 - return this.num(dt.weekday) - case 'EEE': - // like 'Tues' - return weekday('short', false) - case 'EEEE': - // like 'Tuesday' - return weekday('long', false) - case 'EEEEE': - // like 'T' - return weekday('narrow', false) - // months - standalone - case 'L': - // like 1 - return useDateTimeFormatter - ? string({ month: 'numeric', day: 'numeric' }, 'month') - : this.num(dt.month) - case 'LL': - // like 01, doesn't seem to work - return useDateTimeFormatter - ? string({ month: '2-digit', day: 'numeric' }, 'month') - : this.num(dt.month, 2) - case 'LLL': - // like Jan - return month('short', true) - case 'LLLL': - // like January - return month('long', true) - case 'LLLLL': - // like J - return month('narrow', true) - // months - format - case 'M': - // like 1 - return useDateTimeFormatter - ? string({ month: 'numeric' }, 'month') - : this.num(dt.month) - case 'MM': - // like 01 - return useDateTimeFormatter - ? string({ month: '2-digit' }, 'month') - : this.num(dt.month, 2) - case 'MMM': - // like Jan - return month('short', false) - case 'MMMM': - // like January - return month('long', false) - case 'MMMMM': - // like J - return month('narrow', false) - // years - case 'y': - // like 2014 - return useDateTimeFormatter - ? string({ year: 'numeric' }, 'year') - : this.num(dt.year) - case 'yy': - // like 14 - return useDateTimeFormatter - ? string({ year: '2-digit' }, 'year') - : this.num(dt.year.toString().slice(-2), 2) - case 'yyyy': - // like 0012 - return useDateTimeFormatter - ? string({ year: 'numeric' }, 'year') - : this.num(dt.year, 4) - case 'yyyyyy': - // like 000012 - return useDateTimeFormatter - ? string({ year: 'numeric' }, 'year') - : this.num(dt.year, 6) - // eras - case 'G': - // like AD - return era('short') - case 'GG': - // like Anno Domini - return era('long') - case 'GGGGG': - return era('narrow') - case 'kk': - return this.num(dt.weekYear.toString().slice(-2), 2) - case 'kkkk': - return this.num(dt.weekYear, 4) - case 'W': - return this.num(dt.weekNumber) - case 'WW': - return this.num(dt.weekNumber, 2) - case 'n': - return this.num(dt.localWeekNumber) - case 'nn': - return this.num(dt.localWeekNumber, 2) - case 'ii': - return this.num(dt.localWeekYear.toString().slice(-2), 2) - case 'iiii': - return this.num(dt.localWeekYear, 4) - case 'o': - return this.num(dt.ordinal) - case 'ooo': - return this.num(dt.ordinal, 3) - case 'q': - // like 1 - return this.num(dt.quarter) - case 'qq': - // like 01 - return this.num(dt.quarter, 2) - case 'X': - return this.num(Math.floor(dt.ts / 1000)) - case 'x': - return this.num(dt.ts) - default: - return maybeMacro(token) - } - } - - return stringifyTokens(Formatter.parseFormat(fmt), tokenToString) - } - - formatDurationFromString(dur, fmt) { - const tokenToField = (token) => { - switch (token[0]) { - case 'S': - return 'millisecond' - case 's': - return 'second' - case 'm': - return 'minute' - case 'h': - return 'hour' - case 'd': - return 'day' - case 'w': - return 'week' - case 'M': - return 'month' - case 'y': - return 'year' - default: - return null - } - }, - tokenToString = (lildur) => (token) => { - const mapped = tokenToField(token) - if (mapped) { - return this.num(lildur.get(mapped), token.length) - } else { - return token - } - }, - tokens = Formatter.parseFormat(fmt), - realTokens = tokens.reduce( - (found, { literal, val }) => (literal ? found : found.concat(val)), - [] - ), - collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t)) - return stringifyTokens(tokens, tokenToString(collapsed)) - } -} - -/* - * This file handles parsing for well-specified formats. Here's how it works: - * Two things go into parsing: a regex to match with and an extractor to take apart the groups in the match. - * An extractor is just a function that takes a regex match array and returns a { year: ..., month: ... } object - * parse() does the work of executing the regex and applying the extractor. It takes multiple regex/extractor pairs to try in sequence. - * Extractors can take a "cursor" representing the offset in the match to look at. This makes it easy to combine extractors. - * combineExtractors() does the work of combining them, keeping track of the cursor through multiple extractions. - * Some extractions are super dumb and simpleParse and fromStrings help DRY them. - */ - -const ianaRegex = - /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/ - -function combineRegexes(...regexes) { - const full = regexes.reduce((f, r) => f + r.source, '') - return RegExp(`^${full}$`) -} - -function combineExtractors(...extractors) { - return (m) => - extractors - .reduce( - ([mergedVals, mergedZone, cursor], ex) => { - const [val, zone, next] = ex(m, cursor) - return [{ ...mergedVals, ...val }, zone || mergedZone, next] - }, - [{}, null, 1] - ) - .slice(0, 2) -} - -function parse(s, ...patterns) { - if (s == null) { - return [null, null] - } - - for (const [regex, extractor] of patterns) { - const m = regex.exec(s) - if (m) { - return extractor(m) - } - } - return [null, null] -} - -function simpleParse(...keys) { - return (match, cursor) => { - const ret = {} - let i - - for (i = 0; i < keys.length; i++) { - ret[keys[i]] = parseInteger(match[cursor + i]) - } - return [ret, null, cursor + i] - } -} - -// ISO and SQL parsing -const offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/ -const isoExtendedZone = `(?:${offsetRegex.source}?(?:\\[(${ianaRegex.source})\\])?)?` -const isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/ -const isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${isoExtendedZone}`) -const isoTimeExtensionRegex = RegExp(`(?:T${isoTimeRegex.source})?`) -const isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/ -const isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/ -const isoOrdinalRegex = /(\d{4})-?(\d{3})/ -const extractISOWeekData = simpleParse('weekYear', 'weekNumber', 'weekDay') -const extractISOOrdinalData = simpleParse('year', 'ordinal') -const sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/ // dumbed-down version of the ISO one -const sqlTimeRegex = RegExp( - `${isoTimeBaseRegex.source} ?(?:${offsetRegex.source}|(${ianaRegex.source}))?` -) -const sqlTimeExtensionRegex = RegExp(`(?: ${sqlTimeRegex.source})?`) - -function int(match, pos, fallback) { - const m = match[pos] - return isUndefined(m) ? fallback : parseInteger(m) -} - -function extractISOYmd(match, cursor) { - const item = { - year: int(match, cursor), - month: int(match, cursor + 1, 1), - day: int(match, cursor + 2, 1), - } - - return [item, null, cursor + 3] -} - -function extractISOTime(match, cursor) { - const item = { - hours: int(match, cursor, 0), - minutes: int(match, cursor + 1, 0), - seconds: int(match, cursor + 2, 0), - milliseconds: parseMillis(match[cursor + 3]), - } - - return [item, null, cursor + 4] -} - -function extractISOOffset(match, cursor) { - const local = !match[cursor] && !match[cursor + 1], - fullOffset = signedOffset(match[cursor + 1], match[cursor + 2]), - zone = local ? null : FixedOffsetZone.instance(fullOffset) - return [{}, zone, cursor + 3] -} - -function extractIANAZone(match, cursor) { - const zone = match[cursor] ? IANAZone.create(match[cursor]) : null - return [{}, zone, cursor + 1] -} - -// ISO time parsing - -const isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`) - -// ISO duration parsing - -const isoDuration = - /^-?P(?:(?:(-?\d{1,20}(?:\.\d{1,20})?)Y)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20}(?:\.\d{1,20})?)W)?(?:(-?\d{1,20}(?:\.\d{1,20})?)D)?(?:T(?:(-?\d{1,20}(?:\.\d{1,20})?)H)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,20}))?S)?)?)$/ - -function extractISODuration(match) { - const [ - s, - yearStr, - monthStr, - weekStr, - dayStr, - hourStr, - minuteStr, - secondStr, - millisecondsStr, - ] = match - - const hasNegativePrefix = s[0] === '-' - const negativeSeconds = secondStr && secondStr[0] === '-' - - const maybeNegate = (num, force = false) => - num !== undefined && (force || (num && hasNegativePrefix)) ? -num : num - - return [ - { - years: maybeNegate(parseFloating(yearStr)), - months: maybeNegate(parseFloating(monthStr)), - weeks: maybeNegate(parseFloating(weekStr)), - days: maybeNegate(parseFloating(dayStr)), - hours: maybeNegate(parseFloating(hourStr)), - minutes: maybeNegate(parseFloating(minuteStr)), - seconds: maybeNegate(parseFloating(secondStr), secondStr === '-0'), - milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds), - }, - ] -} - -// These are a little braindead. EDT *should* tell us that we're in, say, America/New_York -// and not just that we're in -240 *right now*. But since I don't think these are used that often -// I'm just going to ignore that -const obsOffsets = { - GMT: 0, - EDT: -4 * 60, - EST: -5 * 60, - CDT: -5 * 60, - CST: -6 * 60, - MDT: -6 * 60, - MST: -7 * 60, - PDT: -7 * 60, - PST: -8 * 60, -} - -function fromStrings( - weekdayStr, - yearStr, - monthStr, - dayStr, - hourStr, - minuteStr, - secondStr -) { - const result = { - year: - yearStr.length === 2 - ? untruncateYear(parseInteger(yearStr)) - : parseInteger(yearStr), - month: monthsShort.indexOf(monthStr) + 1, - day: parseInteger(dayStr), - hour: parseInteger(hourStr), - minute: parseInteger(minuteStr), - } - - if (secondStr) result.second = parseInteger(secondStr) - if (weekdayStr) { - result.weekday = - weekdayStr.length > 3 - ? weekdaysLong.indexOf(weekdayStr) + 1 - : weekdaysShort.indexOf(weekdayStr) + 1 - } - - return result -} - -// RFC 2822/5322 -const rfc2822 = - /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/ - -function extractRFC2822(match) { - const [ - , - weekdayStr, - dayStr, - monthStr, - yearStr, - hourStr, - minuteStr, - secondStr, - obsOffset, - milOffset, - offHourStr, - offMinuteStr, - ] = match, - result = fromStrings( - weekdayStr, - yearStr, - monthStr, - dayStr, - hourStr, - minuteStr, - secondStr - ) - - let offset - if (obsOffset) { - offset = obsOffsets[obsOffset] - } else if (milOffset) { - offset = 0 - } else { - offset = signedOffset(offHourStr, offMinuteStr) - } - - return [result, new FixedOffsetZone(offset)] -} - -function preprocessRFC2822(s) { - // Remove comments and folding whitespace and replace multiple-spaces with a single space - return s - .replace(/\([^()]*\)|[\n\t]/g, ' ') - .replace(/(\s\s+)/g, ' ') - .trim() -} - -// http date - -const rfc1123 = - /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/, - rfc850 = - /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/, - ascii = - /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/ - -function extractRFC1123Or850(match) { - const [ - , - weekdayStr, - dayStr, - monthStr, - yearStr, - hourStr, - minuteStr, - secondStr, - ] = match, - result = fromStrings( - weekdayStr, - yearStr, - monthStr, - dayStr, - hourStr, - minuteStr, - secondStr - ) - return [result, FixedOffsetZone.utcInstance] -} - -function extractASCII(match) { - const [ - , - weekdayStr, - monthStr, - dayStr, - hourStr, - minuteStr, - secondStr, - yearStr, - ] = match, - result = fromStrings( - weekdayStr, - yearStr, - monthStr, - dayStr, - hourStr, - minuteStr, - secondStr - ) - return [result, FixedOffsetZone.utcInstance] -} - -const isoYmdWithTimeExtensionRegex = combineRegexes( - isoYmdRegex, - isoTimeExtensionRegex -) -const isoWeekWithTimeExtensionRegex = combineRegexes( - isoWeekRegex, - isoTimeExtensionRegex -) -const isoOrdinalWithTimeExtensionRegex = combineRegexes( - isoOrdinalRegex, - isoTimeExtensionRegex -) -const isoTimeCombinedRegex = combineRegexes(isoTimeRegex) - -const extractISOYmdTimeAndOffset = combineExtractors( - extractISOYmd, - extractISOTime, - extractISOOffset, - extractIANAZone -) -const extractISOWeekTimeAndOffset = combineExtractors( - extractISOWeekData, - extractISOTime, - extractISOOffset, - extractIANAZone -) -const extractISOOrdinalDateAndTime = combineExtractors( - extractISOOrdinalData, - extractISOTime, - extractISOOffset, - extractIANAZone -) -const extractISOTimeAndOffset = combineExtractors( - extractISOTime, - extractISOOffset, - extractIANAZone -) - -/* - * @private - */ - -function parseISODate(s) { - return parse( - s, - [isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], - [isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset], - [isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime], - [isoTimeCombinedRegex, extractISOTimeAndOffset] - ) -} - -function parseRFC2822Date(s) { - return parse(preprocessRFC2822(s), [rfc2822, extractRFC2822]) -} - -function parseHTTPDate(s) { - return parse( - s, - [rfc1123, extractRFC1123Or850], - [rfc850, extractRFC1123Or850], - [ascii, extractASCII] - ) -} - -function parseISODuration(s) { - return parse(s, [isoDuration, extractISODuration]) -} - -const extractISOTimeOnly = combineExtractors(extractISOTime) - -function parseISOTimeOnly(s) { - return parse(s, [isoTimeOnly, extractISOTimeOnly]) -} - -const sqlYmdWithTimeExtensionRegex = combineRegexes( - sqlYmdRegex, - sqlTimeExtensionRegex -) -const sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex) - -const extractISOTimeOffsetAndIANAZone = combineExtractors( - extractISOTime, - extractISOOffset, - extractIANAZone -) - -function parseSQL(s) { - return parse( - s, - [sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset], - [sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone] - ) -} - -const INVALID$2 = 'Invalid Duration' - -// unit conversion constants -const lowOrderMatrix = { - weeks: { - days: 7, - hours: 7 * 24, - minutes: 7 * 24 * 60, - seconds: 7 * 24 * 60 * 60, - milliseconds: 7 * 24 * 60 * 60 * 1000, - }, - days: { - hours: 24, - minutes: 24 * 60, - seconds: 24 * 60 * 60, - milliseconds: 24 * 60 * 60 * 1000, - }, - hours: { minutes: 60, seconds: 60 * 60, milliseconds: 60 * 60 * 1000 }, - minutes: { seconds: 60, milliseconds: 60 * 1000 }, - seconds: { milliseconds: 1000 }, - }, - casualMatrix = { - years: { - quarters: 4, - months: 12, - weeks: 52, - days: 365, - hours: 365 * 24, - minutes: 365 * 24 * 60, - seconds: 365 * 24 * 60 * 60, - milliseconds: 365 * 24 * 60 * 60 * 1000, - }, - quarters: { - months: 3, - weeks: 13, - days: 91, - hours: 91 * 24, - minutes: 91 * 24 * 60, - seconds: 91 * 24 * 60 * 60, - milliseconds: 91 * 24 * 60 * 60 * 1000, - }, - months: { - weeks: 4, - days: 30, - hours: 30 * 24, - minutes: 30 * 24 * 60, - seconds: 30 * 24 * 60 * 60, - milliseconds: 30 * 24 * 60 * 60 * 1000, - }, - - ...lowOrderMatrix, - }, - daysInYearAccurate = 146097.0 / 400, - daysInMonthAccurate = 146097.0 / 4800, - accurateMatrix = { - years: { - quarters: 4, - months: 12, - weeks: daysInYearAccurate / 7, - days: daysInYearAccurate, - hours: daysInYearAccurate * 24, - minutes: daysInYearAccurate * 24 * 60, - seconds: daysInYearAccurate * 24 * 60 * 60, - milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1000, - }, - quarters: { - months: 3, - weeks: daysInYearAccurate / 28, - days: daysInYearAccurate / 4, - hours: (daysInYearAccurate * 24) / 4, - minutes: (daysInYearAccurate * 24 * 60) / 4, - seconds: (daysInYearAccurate * 24 * 60 * 60) / 4, - milliseconds: (daysInYearAccurate * 24 * 60 * 60 * 1000) / 4, - }, - months: { - weeks: daysInMonthAccurate / 7, - days: daysInMonthAccurate, - hours: daysInMonthAccurate * 24, - minutes: daysInMonthAccurate * 24 * 60, - seconds: daysInMonthAccurate * 24 * 60 * 60, - milliseconds: daysInMonthAccurate * 24 * 60 * 60 * 1000, - }, - ...lowOrderMatrix, - } - -// units ordered by size -const orderedUnits$1 = [ - 'years', - 'quarters', - 'months', - 'weeks', - 'days', - 'hours', - 'minutes', - 'seconds', - 'milliseconds', -] - -const reverseUnits = orderedUnits$1.slice(0).reverse() - -// clone really means "create another instance just like this one, but with these changes" -function clone$1(dur, alts, clear = false) { - // deep merge for vals - const conf = { - values: clear ? alts.values : { ...dur.values, ...(alts.values || {}) }, - loc: dur.loc.clone(alts.loc), - conversionAccuracy: alts.conversionAccuracy || dur.conversionAccuracy, - matrix: alts.matrix || dur.matrix, - } - return new Duration(conf) -} - -function durationToMillis(matrix, vals) { - let sum = vals.milliseconds ?? 0 - for (const unit of reverseUnits.slice(1)) { - if (vals[unit]) { - sum += vals[unit] * matrix[unit]['milliseconds'] - } - } - return sum -} - -// NB: mutates parameters -function normalizeValues(matrix, vals) { - // the logic below assumes the overall value of the duration is positive - // if this is not the case, factor is used to make it so - const factor = durationToMillis(matrix, vals) < 0 ? -1 : 1 - - orderedUnits$1.reduceRight((previous, current) => { - if (!isUndefined(vals[current])) { - if (previous) { - const previousVal = vals[previous] * factor - const conv = matrix[current][previous] - - // if (previousVal < 0): - // lower order unit is negative (e.g. { years: 2, days: -2 }) - // normalize this by reducing the higher order unit by the appropriate amount - // and increasing the lower order unit - // this can never make the higher order unit negative, because this function only operates - // on positive durations, so the amount of time represented by the lower order unit cannot - // be larger than the higher order unit - // else: - // lower order unit is positive (e.g. { years: 2, days: 450 } or { years: -2, days: 450 }) - // in this case we attempt to convert as much as possible from the lower order unit into - // the higher order one - // - // Math.floor takes care of both of these cases, rounding away from 0 - // if previousVal < 0 it makes the absolute value larger - // if previousVal >= it makes the absolute value smaller - const rollUp = Math.floor(previousVal / conv) - vals[current] += rollUp * factor - vals[previous] -= rollUp * conv * factor - } - return current - } else { - return previous - } - }, null) - - // try to convert any decimals into smaller units if possible - // for example for { years: 2.5, days: 0, seconds: 0 } we want to get { years: 2, days: 182, hours: 12 } - orderedUnits$1.reduce((previous, current) => { - if (!isUndefined(vals[current])) { - if (previous) { - const fraction = vals[previous] % 1 - vals[previous] -= fraction - vals[current] += fraction * matrix[previous][current] - } - return current - } else { - return previous - } - }, null) -} - -// Remove all properties with a value of 0 from an object -function removeZeroes(vals) { - const newVals = {} - for (const [key, value] of Object.entries(vals)) { - if (value !== 0) { - newVals[key] = value - } - } - return newVals -} - -/** - * A Duration object represents a period of time, like "2 months" or "1 day, 1 hour". Conceptually, it's just a map of units to their quantities, accompanied by some additional configuration and methods for creating, parsing, interrogating, transforming, and formatting them. They can be used on their own or in conjunction with other Luxon types; for example, you can use {@link DateTime#plus} to add a Duration object to a DateTime, producing another DateTime. - * - * Here is a brief overview of commonly used methods and getters in Duration: - * - * * **Creation** To create a Duration, use {@link Duration.fromMillis}, {@link Duration.fromObject}, or {@link Duration.fromISO}. - * * **Unit values** See the {@link Duration#years}, {@link Duration#months}, {@link Duration#weeks}, {@link Duration#days}, {@link Duration#hours}, {@link Duration#minutes}, {@link Duration#seconds}, {@link Duration#milliseconds} accessors. - * * **Configuration** See {@link Duration#locale} and {@link Duration#numberingSystem} accessors. - * * **Transformation** To create new Durations out of old ones use {@link Duration#plus}, {@link Duration#minus}, {@link Duration#normalize}, {@link Duration#set}, {@link Duration#reconfigure}, {@link Duration#shiftTo}, and {@link Duration#negate}. - * * **Output** To convert the Duration into other representations, see {@link Duration#as}, {@link Duration#toISO}, {@link Duration#toFormat}, and {@link Duration#toJSON} - * - * There's are more methods documented below. In addition, for more information on subtler topics like internationalization and validity, see the external documentation. - */ -class Duration { - /** - * @private - */ - constructor(config) { - const accurate = config.conversionAccuracy === 'longterm' || false - let matrix = accurate ? accurateMatrix : casualMatrix - - if (config.matrix) { - matrix = config.matrix - } - - /** - * @access private - */ - this.values = config.values - /** - * @access private - */ - this.loc = config.loc || Locale.create() - /** - * @access private - */ - this.conversionAccuracy = accurate ? 'longterm' : 'casual' - /** - * @access private - */ - this.invalid = config.invalid || null - /** - * @access private - */ - this.matrix = matrix - /** - * @access private - */ - this.isLuxonDuration = true - } - - /** - * Create Duration from a number of milliseconds. - * @param {number} count of milliseconds - * @param {Object} opts - options for parsing - * @param {string} [opts.locale='en-US'] - the locale to use - * @param {string} opts.numberingSystem - the numbering system to use - * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use - * @return {Duration} - */ - static fromMillis(count, opts) { - return Duration.fromObject({ milliseconds: count }, opts) - } - - /** - * Create a Duration from a JavaScript object with keys like 'years' and 'hours'. - * If this object is empty then a zero milliseconds duration is returned. - * @param {Object} obj - the object to create the DateTime from - * @param {number} obj.years - * @param {number} obj.quarters - * @param {number} obj.months - * @param {number} obj.weeks - * @param {number} obj.days - * @param {number} obj.hours - * @param {number} obj.minutes - * @param {number} obj.seconds - * @param {number} obj.milliseconds - * @param {Object} [opts=[]] - options for creating this Duration - * @param {string} [opts.locale='en-US'] - the locale to use - * @param {string} opts.numberingSystem - the numbering system to use - * @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use - * @param {string} [opts.matrix=Object] - the custom conversion system to use - * @return {Duration} - */ - static fromObject(obj, opts = {}) { - if (obj == null || typeof obj !== 'object') { - throw new InvalidArgumentError( - `Duration.fromObject: argument expected to be an object, got ${ - obj === null ? 'null' : typeof obj - }` - ) - } - - return new Duration({ - values: normalizeObject(obj, Duration.normalizeUnit), - loc: Locale.fromObject(opts), - conversionAccuracy: opts.conversionAccuracy, - matrix: opts.matrix, - }) - } - - /** - * Create a Duration from DurationLike. - * - * @param {Object | number | Duration} durationLike - * One of: - * - object with keys like 'years' and 'hours'. - * - number representing milliseconds - * - Duration instance - * @return {Duration} - */ - static fromDurationLike(durationLike) { - if (isNumber(durationLike)) { - return Duration.fromMillis(durationLike) - } else if (Duration.isDuration(durationLike)) { - return durationLike - } else if (typeof durationLike === 'object') { - return Duration.fromObject(durationLike) - } else { - throw new InvalidArgumentError( - `Unknown duration argument ${durationLike} of type ${typeof durationLike}` - ) - } - } - - /** - * Create a Duration from an ISO 8601 duration string. - * @param {string} text - text to parse - * @param {Object} opts - options for parsing - * @param {string} [opts.locale='en-US'] - the locale to use - * @param {string} opts.numberingSystem - the numbering system to use - * @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use - * @param {string} [opts.matrix=Object] - the preset conversion system to use - * @see https://en.wikipedia.org/wiki/ISO_8601#Durations - * @example Duration.fromISO('P3Y6M1W4DT12H30M5S').toObject() //=> { years: 3, months: 6, weeks: 1, days: 4, hours: 12, minutes: 30, seconds: 5 } - * @example Duration.fromISO('PT23H').toObject() //=> { hours: 23 } - * @example Duration.fromISO('P5Y3M').toObject() //=> { years: 5, months: 3 } - * @return {Duration} - */ - static fromISO(text, opts) { - const [parsed] = parseISODuration(text) - if (parsed) { - return Duration.fromObject(parsed, opts) - } else { - return Duration.invalid( - 'unparsable', - `the input "${text}" can't be parsed as ISO 8601` - ) - } - } - - /** - * Create a Duration from an ISO 8601 time string. - * @param {string} text - text to parse - * @param {Object} opts - options for parsing - * @param {string} [opts.locale='en-US'] - the locale to use - * @param {string} opts.numberingSystem - the numbering system to use - * @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use - * @param {string} [opts.matrix=Object] - the conversion system to use - * @see https://en.wikipedia.org/wiki/ISO_8601#Times - * @example Duration.fromISOTime('11:22:33.444').toObject() //=> { hours: 11, minutes: 22, seconds: 33, milliseconds: 444 } - * @example Duration.fromISOTime('11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } - * @example Duration.fromISOTime('T11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } - * @example Duration.fromISOTime('1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } - * @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 } - * @return {Duration} - */ - static fromISOTime(text, opts) { - const [parsed] = parseISOTimeOnly(text) - if (parsed) { - return Duration.fromObject(parsed, opts) - } else { - return Duration.invalid( - 'unparsable', - `the input "${text}" can't be parsed as ISO 8601` - ) - } - } - - /** - * Create an invalid Duration. - * @param {string} reason - simple string of why this datetime is invalid. Should not contain parameters or anything else data-dependent - * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information - * @return {Duration} - */ - static invalid(reason, explanation = null) { - if (!reason) { - throw new InvalidArgumentError( - 'need to specify a reason the Duration is invalid' - ) - } - - const invalid = - reason instanceof Invalid ? reason : new Invalid(reason, explanation) - - if (Settings.throwOnInvalid) { - throw new InvalidDurationError(invalid) - } else { - return new Duration({ invalid }) - } - } - - /** - * @private - */ - static normalizeUnit(unit) { - const normalized = { - year: 'years', - years: 'years', - quarter: 'quarters', - quarters: 'quarters', - month: 'months', - months: 'months', - week: 'weeks', - weeks: 'weeks', - day: 'days', - days: 'days', - hour: 'hours', - hours: 'hours', - minute: 'minutes', - minutes: 'minutes', - second: 'seconds', - seconds: 'seconds', - millisecond: 'milliseconds', - milliseconds: 'milliseconds', - }[unit ? unit.toLowerCase() : unit] - - if (!normalized) throw new InvalidUnitError(unit) - - return normalized - } - - /** - * Check if an object is a Duration. Works across context boundaries - * @param {object} o - * @return {boolean} - */ - static isDuration(o) { - return (o && o.isLuxonDuration) || false - } - - /** - * Get the locale of a Duration, such 'en-GB' - * @type {string} - */ - get locale() { - return this.isValid ? this.loc.locale : null - } - - /** - * Get the numbering system of a Duration, such 'beng'. The numbering system is used when formatting the Duration - * - * @type {string} - */ - get numberingSystem() { - return this.isValid ? this.loc.numberingSystem : null - } - - /** - * Returns a string representation of this Duration formatted according to the specified format string. You may use these tokens: - * * `S` for milliseconds - * * `s` for seconds - * * `m` for minutes - * * `h` for hours - * * `d` for days - * * `w` for weeks - * * `M` for months - * * `y` for years - * Notes: - * * Add padding by repeating the token, e.g. "yy" pads the years to two digits, "hhhh" pads the hours out to four digits - * * Tokens can be escaped by wrapping with single quotes. - * * The duration will be converted to the set of units in the format string using {@link Duration#shiftTo} and the Durations's conversion accuracy setting. - * @param {string} fmt - the format string - * @param {Object} opts - options - * @param {boolean} [opts.floor=true] - floor numerical values - * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2" - * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002" - * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000" - * @return {string} - */ - toFormat(fmt, opts = {}) { - // reverse-compat since 1.2; we always round down now, never up, and we do it by default - const fmtOpts = { - ...opts, - floor: opts.round !== false && opts.floor !== false, - } - return this.isValid - ? Formatter.create(this.loc, fmtOpts).formatDurationFromString(this, fmt) - : INVALID$2 - } - - /** - * Returns a string representation of a Duration with all units included. - * To modify its behavior, use `listStyle` and any Intl.NumberFormat option, though `unitDisplay` is especially relevant. - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options - * @param {Object} opts - Formatting options. Accepts the same keys as the options parameter of the native `Intl.NumberFormat` constructor, as well as `listStyle`. - * @param {string} [opts.listStyle='narrow'] - How to format the merged list. Corresponds to the `style` property of the options parameter of the native `Intl.ListFormat` constructor. - * @example - * ```js - * var dur = Duration.fromObject({ days: 1, hours: 5, minutes: 6 }) - * dur.toHuman() //=> '1 day, 5 hours, 6 minutes' - * dur.toHuman({ listStyle: "long" }) //=> '1 day, 5 hours, and 6 minutes' - * dur.toHuman({ unitDisplay: "short" }) //=> '1 day, 5 hr, 6 min' - * ``` - */ - toHuman(opts = {}) { - if (!this.isValid) return INVALID$2 - - const l = orderedUnits$1 - .map((unit) => { - const val = this.values[unit] - if (isUndefined(val)) { - return null - } - return this.loc - .numberFormatter({ - style: 'unit', - unitDisplay: 'long', - ...opts, - unit: unit.slice(0, -1), - }) - .format(val) - }) - .filter((n) => n) - - return this.loc - .listFormatter({ - type: 'conjunction', - style: opts.listStyle || 'narrow', - ...opts, - }) - .format(l) - } - - /** - * Returns a JavaScript object with this Duration's values. - * @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toObject() //=> { years: 1, days: 6, seconds: 2 } - * @return {Object} - */ - toObject() { - if (!this.isValid) return {} - return { ...this.values } - } - - /** - * Returns an ISO 8601-compliant string representation of this Duration. - * @see https://en.wikipedia.org/wiki/ISO_8601#Durations - * @example Duration.fromObject({ years: 3, seconds: 45 }).toISO() //=> 'P3YT45S' - * @example Duration.fromObject({ months: 4, seconds: 45 }).toISO() //=> 'P4MT45S' - * @example Duration.fromObject({ months: 5 }).toISO() //=> 'P5M' - * @example Duration.fromObject({ minutes: 5 }).toISO() //=> 'PT5M' - * @example Duration.fromObject({ milliseconds: 6 }).toISO() //=> 'PT0.006S' - * @return {string} - */ - toISO() { - // we could use the formatter, but this is an easier way to get the minimum string - if (!this.isValid) return null - - let s = 'P' - if (this.years !== 0) s += this.years + 'Y' - if (this.months !== 0 || this.quarters !== 0) - s += this.months + this.quarters * 3 + 'M' - if (this.weeks !== 0) s += this.weeks + 'W' - if (this.days !== 0) s += this.days + 'D' - if ( - this.hours !== 0 || - this.minutes !== 0 || - this.seconds !== 0 || - this.milliseconds !== 0 - ) - s += 'T' - if (this.hours !== 0) s += this.hours + 'H' - if (this.minutes !== 0) s += this.minutes + 'M' - if (this.seconds !== 0 || this.milliseconds !== 0) - // this will handle "floating point madness" by removing extra decimal places - // https://stackoverflow.com/questions/588004/is-floating-point-math-broken - s += roundTo(this.seconds + this.milliseconds / 1000, 3) + 'S' - if (s === 'P') s += 'T0S' - return s - } - - /** - * Returns an ISO 8601-compliant string representation of this Duration, formatted as a time of day. - * Note that this will return null if the duration is invalid, negative, or equal to or greater than 24 hours. - * @see https://en.wikipedia.org/wiki/ISO_8601#Times - * @param {Object} opts - options - * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 - * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 - * @param {boolean} [opts.includePrefix=false] - include the `T` prefix - * @param {string} [opts.format='extended'] - choose between the basic and extended format - * @example Duration.fromObject({ hours: 11 }).toISOTime() //=> '11:00:00.000' - * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressMilliseconds: true }) //=> '11:00:00' - * @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressSeconds: true }) //=> '11:00' - * @example Duration.fromObject({ hours: 11 }).toISOTime({ includePrefix: true }) //=> 'T11:00:00.000' - * @example Duration.fromObject({ hours: 11 }).toISOTime({ format: 'basic' }) //=> '110000.000' - * @return {string} - */ - toISOTime(opts = {}) { - if (!this.isValid) return null - - const millis = this.toMillis() - if (millis < 0 || millis >= 86400000) return null - - opts = { - suppressMilliseconds: false, - suppressSeconds: false, - includePrefix: false, - format: 'extended', - ...opts, - includeOffset: false, - } - - const dateTime = DateTime.fromMillis(millis, { zone: 'UTC' }) - return dateTime.toISOTime(opts) - } - - /** - * Returns an ISO 8601 representation of this Duration appropriate for use in JSON. - * @return {string} - */ - toJSON() { - return this.toISO() - } - - /** - * Returns an ISO 8601 representation of this Duration appropriate for use in debugging. - * @return {string} - */ - toString() { - return this.toISO() - } - - /** - * Returns a string representation of this Duration appropriate for the REPL. - * @return {string} - */ - [Symbol.for('nodejs.util.inspect.custom')]() { - if (this.isValid) { - return `Duration { values: ${JSON.stringify(this.values)} }` - } else { - return `Duration { Invalid, reason: ${this.invalidReason} }` - } - } - - /** - * Returns an milliseconds value of this Duration. - * @return {number} - */ - toMillis() { - if (!this.isValid) return NaN - - return durationToMillis(this.matrix, this.values) - } - - /** - * Returns an milliseconds value of this Duration. Alias of {@link toMillis} - * @return {number} - */ - valueOf() { - return this.toMillis() - } - - /** - * Make this Duration longer by the specified amount. Return a newly-constructed Duration. - * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() - * @return {Duration} - */ - plus(duration) { - if (!this.isValid) return this - - const dur = Duration.fromDurationLike(duration), - result = {} - - for (const k of orderedUnits$1) { - if (hasOwnProperty(dur.values, k) || hasOwnProperty(this.values, k)) { - result[k] = dur.get(k) + this.get(k) - } - } - - return clone$1(this, { values: result }, true) - } - - /** - * Make this Duration shorter by the specified amount. Return a newly-constructed Duration. - * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() - * @return {Duration} - */ - minus(duration) { - if (!this.isValid) return this - - const dur = Duration.fromDurationLike(duration) - return this.plus(dur.negate()) - } - - /** - * Scale this Duration by the specified amount. Return a newly-constructed Duration. - * @param {function} fn - The function to apply to each unit. Arity is 1 or 2: the value of the unit and, optionally, the unit name. Must return a number. - * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits(x => x * 2) //=> { hours: 2, minutes: 60 } - * @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits((x, u) => u === "hours" ? x * 2 : x) //=> { hours: 2, minutes: 30 } - * @return {Duration} - */ - mapUnits(fn) { - if (!this.isValid) return this - const result = {} - for (const k of Object.keys(this.values)) { - result[k] = asNumber(fn(this.values[k], k)) - } - return clone$1(this, { values: result }, true) - } - - /** - * Get the value of unit. - * @param {string} unit - a unit such as 'minute' or 'day' - * @example Duration.fromObject({years: 2, days: 3}).get('years') //=> 2 - * @example Duration.fromObject({years: 2, days: 3}).get('months') //=> 0 - * @example Duration.fromObject({years: 2, days: 3}).get('days') //=> 3 - * @return {number} - */ - get(unit) { - return this[Duration.normalizeUnit(unit)] - } - - /** - * "Set" the values of specified units. Return a newly-constructed Duration. - * @param {Object} values - a mapping of units to numbers - * @example dur.set({ years: 2017 }) - * @example dur.set({ hours: 8, minutes: 30 }) - * @return {Duration} - */ - set(values) { - if (!this.isValid) return this - - const mixed = { - ...this.values, - ...normalizeObject(values, Duration.normalizeUnit), - } - return clone$1(this, { values: mixed }) - } - - /** - * "Set" the locale and/or numberingSystem. Returns a newly-constructed Duration. - * @example dur.reconfigure({ locale: 'en-GB' }) - * @return {Duration} - */ - reconfigure({ locale, numberingSystem, conversionAccuracy, matrix } = {}) { - const loc = this.loc.clone({ locale, numberingSystem }) - const opts = { loc, matrix, conversionAccuracy } - return clone$1(this, opts) - } - - /** - * Return the length of the duration in the specified unit. - * @param {string} unit - a unit such as 'minutes' or 'days' - * @example Duration.fromObject({years: 1}).as('days') //=> 365 - * @example Duration.fromObject({years: 1}).as('months') //=> 12 - * @example Duration.fromObject({hours: 60}).as('days') //=> 2.5 - * @return {number} - */ - as(unit) { - return this.isValid ? this.shiftTo(unit).get(unit) : NaN - } - - /** - * Reduce this Duration to its canonical representation in its current units. - * Assuming the overall value of the Duration is positive, this means: - * - excessive values for lower-order units are converted to higher-order units (if possible, see first and second example) - * - negative lower-order units are converted to higher order units (there must be such a higher order unit, otherwise - * the overall value would be negative, see third example) - * - fractional values for higher-order units are converted to lower-order units (if possible, see fourth example) - * - * If the overall value is negative, the result of this method is equivalent to `this.negate().normalize().negate()`. - * @example Duration.fromObject({ years: 2, days: 5000 }).normalize().toObject() //=> { years: 15, days: 255 } - * @example Duration.fromObject({ days: 5000 }).normalize().toObject() //=> { days: 5000 } - * @example Duration.fromObject({ hours: 12, minutes: -45 }).normalize().toObject() //=> { hours: 11, minutes: 15 } - * @example Duration.fromObject({ years: 2.5, days: 0, hours: 0 }).normalize().toObject() //=> { years: 2, days: 182, hours: 12 } - * @return {Duration} - */ - normalize() { - if (!this.isValid) return this - const vals = this.toObject() - normalizeValues(this.matrix, vals) - return clone$1(this, { values: vals }, true) - } - - /** - * Rescale units to its largest representation - * @example Duration.fromObject({ milliseconds: 90000 }).rescale().toObject() //=> { minutes: 1, seconds: 30 } - * @return {Duration} - */ - rescale() { - if (!this.isValid) return this - const vals = removeZeroes(this.normalize().shiftToAll().toObject()) - return clone$1(this, { values: vals }, true) - } - - /** - * Convert this Duration into its representation in a different set of units. - * @example Duration.fromObject({ hours: 1, seconds: 30 }).shiftTo('minutes', 'milliseconds').toObject() //=> { minutes: 60, milliseconds: 30000 } - * @return {Duration} - */ - shiftTo(...units) { - if (!this.isValid) return this - - if (units.length === 0) { - return this - } - - units = units.map((u) => Duration.normalizeUnit(u)) - - const built = {}, - accumulated = {}, - vals = this.toObject() - let lastUnit - - for (const k of orderedUnits$1) { - if (units.indexOf(k) >= 0) { - lastUnit = k - - let own = 0 - - // anything we haven't boiled down yet should get boiled to this unit - for (const ak in accumulated) { - own += this.matrix[ak][k] * accumulated[ak] - accumulated[ak] = 0 - } - - // plus anything that's already in this unit - if (isNumber(vals[k])) { - own += vals[k] - } - - // only keep the integer part for now in the hopes of putting any decimal part - // into a smaller unit later - const i = Math.trunc(own) - built[k] = i - accumulated[k] = (own * 1000 - i * 1000) / 1000 - - // otherwise, keep it in the wings to boil it later - } else if (isNumber(vals[k])) { - accumulated[k] = vals[k] - } - } - - // anything leftover becomes the decimal for the last unit - // lastUnit must be defined since units is not empty - for (const key in accumulated) { - if (accumulated[key] !== 0) { - built[lastUnit] += - key === lastUnit - ? accumulated[key] - : accumulated[key] / this.matrix[lastUnit][key] - } - } - - normalizeValues(this.matrix, built) - return clone$1(this, { values: built }, true) - } - - /** - * Shift this Duration to all available units. - * Same as shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds") - * @return {Duration} - */ - shiftToAll() { - if (!this.isValid) return this - return this.shiftTo( - 'years', - 'months', - 'weeks', - 'days', - 'hours', - 'minutes', - 'seconds', - 'milliseconds' - ) - } - - /** - * Return the negative of this Duration. - * @example Duration.fromObject({ hours: 1, seconds: 30 }).negate().toObject() //=> { hours: -1, seconds: -30 } - * @return {Duration} - */ - negate() { - if (!this.isValid) return this - const negated = {} - for (const k of Object.keys(this.values)) { - negated[k] = this.values[k] === 0 ? 0 : -this.values[k] - } - return clone$1(this, { values: negated }, true) - } - - /** - * Get the years. - * @type {number} - */ - get years() { - return this.isValid ? this.values.years || 0 : NaN - } - - /** - * Get the quarters. - * @type {number} - */ - get quarters() { - return this.isValid ? this.values.quarters || 0 : NaN - } - - /** - * Get the months. - * @type {number} - */ - get months() { - return this.isValid ? this.values.months || 0 : NaN - } - - /** - * Get the weeks - * @type {number} - */ - get weeks() { - return this.isValid ? this.values.weeks || 0 : NaN - } - - /** - * Get the days. - * @type {number} - */ - get days() { - return this.isValid ? this.values.days || 0 : NaN - } - - /** - * Get the hours. - * @type {number} - */ - get hours() { - return this.isValid ? this.values.hours || 0 : NaN - } - - /** - * Get the minutes. - * @type {number} - */ - get minutes() { - return this.isValid ? this.values.minutes || 0 : NaN - } - - /** - * Get the seconds. - * @return {number} - */ - get seconds() { - return this.isValid ? this.values.seconds || 0 : NaN - } - - /** - * Get the milliseconds. - * @return {number} - */ - get milliseconds() { - return this.isValid ? this.values.milliseconds || 0 : NaN - } - - /** - * Returns whether the Duration is invalid. Invalid durations are returned by diff operations - * on invalid DateTimes or Intervals. - * @return {boolean} - */ - get isValid() { - return this.invalid === null - } - - /** - * Returns an error code if this Duration became invalid, or null if the Duration is valid - * @return {string} - */ - get invalidReason() { - return this.invalid ? this.invalid.reason : null - } - - /** - * Returns an explanation of why this Duration became invalid, or null if the Duration is valid - * @type {string} - */ - get invalidExplanation() { - return this.invalid ? this.invalid.explanation : null - } - - /** - * Equality check - * Two Durations are equal iff they have the same units and the same values for each unit. - * @param {Duration} other - * @return {boolean} - */ - equals(other) { - if (!this.isValid || !other.isValid) { - return false - } - - if (!this.loc.equals(other.loc)) { - return false - } - - function eq(v1, v2) { - // Consider 0 and undefined as equal - if (v1 === undefined || v1 === 0) return v2 === undefined || v2 === 0 - return v1 === v2 - } - - for (const u of orderedUnits$1) { - if (!eq(this.values[u], other.values[u])) { - return false - } - } - return true - } -} - -const INVALID$1 = 'Invalid Interval' - -// checks if the start is equal to or before the end -function validateStartEnd(start, end) { - if (!start || !start.isValid) { - return Interval.invalid('missing or invalid start') - } else if (!end || !end.isValid) { - return Interval.invalid('missing or invalid end') - } else if (end < start) { - return Interval.invalid( - 'end before start', - `The end of an interval must be after its start, but you had start=${start.toISO()} and end=${end.toISO()}` - ) - } else { - return null - } -} - -/** - * An Interval object represents a half-open interval of time, where each endpoint is a {@link DateTime}. Conceptually, it's a container for those two endpoints, accompanied by methods for creating, parsing, interrogating, comparing, transforming, and formatting them. - * - * Here is a brief overview of the most commonly used methods and getters in Interval: - * - * * **Creation** To create an Interval, use {@link Interval.fromDateTimes}, {@link Interval.after}, {@link Interval.before}, or {@link Interval.fromISO}. - * * **Accessors** Use {@link Interval#start} and {@link Interval#end} to get the start and end. - * * **Interrogation** To analyze the Interval, use {@link Interval#count}, {@link Interval#length}, {@link Interval#hasSame}, {@link Interval#contains}, {@link Interval#isAfter}, or {@link Interval#isBefore}. - * * **Transformation** To create other Intervals out of this one, use {@link Interval#set}, {@link Interval#splitAt}, {@link Interval#splitBy}, {@link Interval#divideEqually}, {@link Interval.merge}, {@link Interval.xor}, {@link Interval#union}, {@link Interval#intersection}, or {@link Interval#difference}. - * * **Comparison** To compare this Interval to another one, use {@link Interval#equals}, {@link Interval#overlaps}, {@link Interval#abutsStart}, {@link Interval#abutsEnd}, {@link Interval#engulfs} - * * **Output** To convert the Interval into other representations, see {@link Interval#toString}, {@link Interval#toLocaleString}, {@link Interval#toISO}, {@link Interval#toISODate}, {@link Interval#toISOTime}, {@link Interval#toFormat}, and {@link Interval#toDuration}. - */ -class Interval { - /** - * @private - */ - constructor(config) { - /** - * @access private - */ - this.s = config.start - /** - * @access private - */ - this.e = config.end - /** - * @access private - */ - this.invalid = config.invalid || null - /** - * @access private - */ - this.isLuxonInterval = true - } - - /** - * Create an invalid Interval. - * @param {string} reason - simple string of why this Interval is invalid. Should not contain parameters or anything else data-dependent - * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information - * @return {Interval} - */ - static invalid(reason, explanation = null) { - if (!reason) { - throw new InvalidArgumentError( - 'need to specify a reason the Interval is invalid' - ) - } - - const invalid = - reason instanceof Invalid ? reason : new Invalid(reason, explanation) - - if (Settings.throwOnInvalid) { - throw new InvalidIntervalError(invalid) - } else { - return new Interval({ invalid }) - } - } - - /** - * Create an Interval from a start DateTime and an end DateTime. Inclusive of the start but not the end. - * @param {DateTime|Date|Object} start - * @param {DateTime|Date|Object} end - * @return {Interval} - */ - static fromDateTimes(start, end) { - const builtStart = friendlyDateTime(start), - builtEnd = friendlyDateTime(end) - - const validateError = validateStartEnd(builtStart, builtEnd) - - if (validateError == null) { - return new Interval({ - start: builtStart, - end: builtEnd, - }) - } else { - return validateError - } - } - - /** - * Create an Interval from a start DateTime and a Duration to extend to. - * @param {DateTime|Date|Object} start - * @param {Duration|Object|number} duration - the length of the Interval. - * @return {Interval} - */ - static after(start, duration) { - const dur = Duration.fromDurationLike(duration), - dt = friendlyDateTime(start) - return Interval.fromDateTimes(dt, dt.plus(dur)) - } - - /** - * Create an Interval from an end DateTime and a Duration to extend backwards to. - * @param {DateTime|Date|Object} end - * @param {Duration|Object|number} duration - the length of the Interval. - * @return {Interval} - */ - static before(end, duration) { - const dur = Duration.fromDurationLike(duration), - dt = friendlyDateTime(end) - return Interval.fromDateTimes(dt.minus(dur), dt) - } - - /** - * Create an Interval from an ISO 8601 string. - * Accepts `/`, `/`, and `/` formats. - * @param {string} text - the ISO string to parse - * @param {Object} [opts] - options to pass {@link DateTime#fromISO} and optionally {@link Duration#fromISO} - * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals - * @return {Interval} - */ - static fromISO(text, opts) { - const [s, e] = (text || '').split('/', 2) - if (s && e) { - let start, startIsValid - try { - start = DateTime.fromISO(s, opts) - startIsValid = start.isValid - } catch (e) { - startIsValid = false - } - - let end, endIsValid - try { - end = DateTime.fromISO(e, opts) - endIsValid = end.isValid - } catch (e) { - endIsValid = false - } - - if (startIsValid && endIsValid) { - return Interval.fromDateTimes(start, end) - } - - if (startIsValid) { - const dur = Duration.fromISO(e, opts) - if (dur.isValid) { - return Interval.after(start, dur) - } - } else if (endIsValid) { - const dur = Duration.fromISO(s, opts) - if (dur.isValid) { - return Interval.before(end, dur) - } - } - } - return Interval.invalid( - 'unparsable', - `the input "${text}" can't be parsed as ISO 8601` - ) - } - - /** - * Check if an object is an Interval. Works across context boundaries - * @param {object} o - * @return {boolean} - */ - static isInterval(o) { - return (o && o.isLuxonInterval) || false - } - - /** - * Returns the start of the Interval - * @type {DateTime} - */ - get start() { - return this.isValid ? this.s : null - } - - /** - * Returns the end of the Interval - * @type {DateTime} - */ - get end() { - return this.isValid ? this.e : null - } - - /** - * Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'. - * @type {boolean} - */ - get isValid() { - return this.invalidReason === null - } - - /** - * Returns an error code if this Interval is invalid, or null if the Interval is valid - * @type {string} - */ - get invalidReason() { - return this.invalid ? this.invalid.reason : null - } - - /** - * Returns an explanation of why this Interval became invalid, or null if the Interval is valid - * @type {string} - */ - get invalidExplanation() { - return this.invalid ? this.invalid.explanation : null - } - - /** - * Returns the length of the Interval in the specified unit. - * @param {string} unit - the unit (such as 'hours' or 'days') to return the length in. - * @return {number} - */ - length(unit = 'milliseconds') { - return this.isValid ? this.toDuration(...[unit]).get(unit) : NaN - } - - /** - * Returns the count of minutes, hours, days, months, or years included in the Interval, even in part. - * Unlike {@link Interval#length} this counts sections of the calendar, not periods of time, e.g. specifying 'day' - * asks 'what dates are included in this interval?', not 'how many days long is this interval?' - * @param {string} [unit='milliseconds'] - the unit of time to count. - * @param {Object} opts - options - * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week; this operation will always use the locale of the start DateTime - * @return {number} - */ - count(unit = 'milliseconds', opts) { - if (!this.isValid) return NaN - const start = this.start.startOf(unit, opts) - let end - if (opts?.useLocaleWeeks) { - end = this.end.reconfigure({ locale: start.locale }) - } else { - end = this.end - } - end = end.startOf(unit, opts) - return ( - Math.floor(end.diff(start, unit).get(unit)) + - (end.valueOf() !== this.end.valueOf()) - ) - } - - /** - * Returns whether this Interval's start and end are both in the same unit of time - * @param {string} unit - the unit of time to check sameness on - * @return {boolean} - */ - hasSame(unit) { - return this.isValid - ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit) - : false - } - - /** - * Return whether this Interval has the same start and end DateTimes. - * @return {boolean} - */ - isEmpty() { - return this.s.valueOf() === this.e.valueOf() - } - - /** - * Return whether this Interval's start is after the specified DateTime. - * @param {DateTime} dateTime - * @return {boolean} - */ - isAfter(dateTime) { - if (!this.isValid) return false - return this.s > dateTime - } - - /** - * Return whether this Interval's end is before the specified DateTime. - * @param {DateTime} dateTime - * @return {boolean} - */ - isBefore(dateTime) { - if (!this.isValid) return false - return this.e <= dateTime - } - - /** - * Return whether this Interval contains the specified DateTime. - * @param {DateTime} dateTime - * @return {boolean} - */ - contains(dateTime) { - if (!this.isValid) return false - return this.s <= dateTime && this.e > dateTime - } - - /** - * "Sets" the start and/or end dates. Returns a newly-constructed Interval. - * @param {Object} values - the values to set - * @param {DateTime} values.start - the starting DateTime - * @param {DateTime} values.end - the ending DateTime - * @return {Interval} - */ - set({ start, end } = {}) { - if (!this.isValid) return this - return Interval.fromDateTimes(start || this.s, end || this.e) - } - - /** - * Split this Interval at each of the specified DateTimes - * @param {...DateTime} dateTimes - the unit of time to count. - * @return {Array} - */ - splitAt(...dateTimes) { - if (!this.isValid) return [] - const sorted = dateTimes - .map(friendlyDateTime) - .filter((d) => this.contains(d)) - .sort((a, b) => a.toMillis() - b.toMillis()), - results = [] - let { s } = this, - i = 0 - - while (s < this.e) { - const added = sorted[i] || this.e, - next = +added > +this.e ? this.e : added - results.push(Interval.fromDateTimes(s, next)) - s = next - i += 1 - } - - return results - } - - /** - * Split this Interval into smaller Intervals, each of the specified length. - * Left over time is grouped into a smaller interval - * @param {Duration|Object|number} duration - The length of each resulting interval. - * @return {Array} - */ - splitBy(duration) { - const dur = Duration.fromDurationLike(duration) - - if (!this.isValid || !dur.isValid || dur.as('milliseconds') === 0) { - return [] - } - - let { s } = this, - idx = 1, - next - - const results = [] - while (s < this.e) { - const added = this.start.plus(dur.mapUnits((x) => x * idx)) - next = +added > +this.e ? this.e : added - results.push(Interval.fromDateTimes(s, next)) - s = next - idx += 1 - } - - return results - } - - /** - * Split this Interval into the specified number of smaller intervals. - * @param {number} numberOfParts - The number of Intervals to divide the Interval into. - * @return {Array} - */ - divideEqually(numberOfParts) { - if (!this.isValid) return [] - return this.splitBy(this.length() / numberOfParts).slice(0, numberOfParts) - } - - /** - * Return whether this Interval overlaps with the specified Interval - * @param {Interval} other - * @return {boolean} - */ - overlaps(other) { - return this.e > other.s && this.s < other.e - } - - /** - * Return whether this Interval's end is adjacent to the specified Interval's start. - * @param {Interval} other - * @return {boolean} - */ - abutsStart(other) { - if (!this.isValid) return false - return +this.e === +other.s - } - - /** - * Return whether this Interval's start is adjacent to the specified Interval's end. - * @param {Interval} other - * @return {boolean} - */ - abutsEnd(other) { - if (!this.isValid) return false - return +other.e === +this.s - } - - /** - * Return whether this Interval engulfs the start and end of the specified Interval. - * @param {Interval} other - * @return {boolean} - */ - engulfs(other) { - if (!this.isValid) return false - return this.s <= other.s && this.e >= other.e - } - - /** - * Return whether this Interval has the same start and end as the specified Interval. - * @param {Interval} other - * @return {boolean} - */ - equals(other) { - if (!this.isValid || !other.isValid) { - return false - } - - return this.s.equals(other.s) && this.e.equals(other.e) - } - - /** - * Return an Interval representing the intersection of this Interval and the specified Interval. - * Specifically, the resulting Interval has the maximum start time and the minimum end time of the two Intervals. - * Returns null if the intersection is empty, meaning, the intervals don't intersect. - * @param {Interval} other - * @return {Interval} - */ - intersection(other) { - if (!this.isValid) return this - const s = this.s > other.s ? this.s : other.s, - e = this.e < other.e ? this.e : other.e - - if (s >= e) { - return null - } else { - return Interval.fromDateTimes(s, e) - } - } - - /** - * Return an Interval representing the union of this Interval and the specified Interval. - * Specifically, the resulting Interval has the minimum start time and the maximum end time of the two Intervals. - * @param {Interval} other - * @return {Interval} - */ - union(other) { - if (!this.isValid) return this - const s = this.s < other.s ? this.s : other.s, - e = this.e > other.e ? this.e : other.e - return Interval.fromDateTimes(s, e) - } - - /** - * Merge an array of Intervals into a equivalent minimal set of Intervals. - * Combines overlapping and adjacent Intervals. - * @param {Array} intervals - * @return {Array} - */ - static merge(intervals) { - const [found, final] = intervals - .sort((a, b) => a.s - b.s) - .reduce( - ([sofar, current], item) => { - if (!current) { - return [sofar, item] - } else if (current.overlaps(item) || current.abutsStart(item)) { - return [sofar, current.union(item)] - } else { - return [sofar.concat([current]), item] - } - }, - [[], null] - ) - if (final) { - found.push(final) - } - return found - } - - /** - * Return an array of Intervals representing the spans of time that only appear in one of the specified Intervals. - * @param {Array} intervals - * @return {Array} - */ - static xor(intervals) { - let start = null, - currentCount = 0 - const results = [], - ends = intervals.map((i) => [ - { time: i.s, type: 's' }, - { time: i.e, type: 'e' }, - ]), - flattened = Array.prototype.concat(...ends), - arr = flattened.sort((a, b) => a.time - b.time) - - for (const i of arr) { - currentCount += i.type === 's' ? 1 : -1 - - if (currentCount === 1) { - start = i.time - } else { - if (start && +start !== +i.time) { - results.push(Interval.fromDateTimes(start, i.time)) - } - - start = null - } - } - - return Interval.merge(results) - } - - /** - * Return an Interval representing the span of time in this Interval that doesn't overlap with any of the specified Intervals. - * @param {...Interval} intervals - * @return {Array} - */ - difference(...intervals) { - return Interval.xor([this].concat(intervals)) - .map((i) => this.intersection(i)) - .filter((i) => i && !i.isEmpty()) - } - - /** - * Returns a string representation of this Interval appropriate for debugging. - * @return {string} - */ - toString() { - if (!this.isValid) return INVALID$1 - return `[${this.s.toISO()} – ${this.e.toISO()})` - } - - /** - * Returns a string representation of this Interval appropriate for the REPL. - * @return {string} - */ - [Symbol.for('nodejs.util.inspect.custom')]() { - if (this.isValid) { - return `Interval { start: ${this.s.toISO()}, end: ${this.e.toISO()} }` - } else { - return `Interval { Invalid, reason: ${this.invalidReason} }` - } - } - - /** - * Returns a localized string representing this Interval. Accepts the same options as the - * Intl.DateTimeFormat constructor and any presets defined by Luxon, such as - * {@link DateTime.DATE_FULL} or {@link DateTime.TIME_SIMPLE}. The exact behavior of this method - * is browser-specific, but in general it will return an appropriate representation of the - * Interval in the assigned locale. Defaults to the system's locale if no locale has been - * specified. - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat - * @param {Object} [formatOpts=DateTime.DATE_SHORT] - Either a DateTime preset or - * Intl.DateTimeFormat constructor options. - * @param {Object} opts - Options to override the configuration of the start DateTime. - * @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(); //=> 11/7/2022 – 11/8/2022 - * @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL); //=> November 7 – 8, 2022 - * @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL, { locale: 'fr-FR' }); //=> 7–8 novembre 2022 - * @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString(DateTime.TIME_SIMPLE); //=> 6:00 – 8:00 PM - * @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> Mon, Nov 07, 6:00 – 8:00 p - * @return {string} - */ - toLocaleString(formatOpts = DATE_SHORT, opts = {}) { - return this.isValid - ? Formatter.create(this.s.loc.clone(opts), formatOpts).formatInterval( - this - ) - : INVALID$1 - } - - /** - * Returns an ISO 8601-compliant string representation of this Interval. - * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals - * @param {Object} opts - The same options as {@link DateTime#toISO} - * @return {string} - */ - toISO(opts) { - if (!this.isValid) return INVALID$1 - return `${this.s.toISO(opts)}/${this.e.toISO(opts)}` - } - - /** - * Returns an ISO 8601-compliant string representation of date of this Interval. - * The time components are ignored. - * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals - * @return {string} - */ - toISODate() { - if (!this.isValid) return INVALID$1 - return `${this.s.toISODate()}/${this.e.toISODate()}` - } - - /** - * Returns an ISO 8601-compliant string representation of time of this Interval. - * The date components are ignored. - * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals - * @param {Object} opts - The same options as {@link DateTime#toISO} - * @return {string} - */ - toISOTime(opts) { - if (!this.isValid) return INVALID$1 - return `${this.s.toISOTime(opts)}/${this.e.toISOTime(opts)}` - } - - /** - * Returns a string representation of this Interval formatted according to the specified format - * string. **You may not want this.** See {@link Interval#toLocaleString} for a more flexible - * formatting tool. - * @param {string} dateFormat - The format string. This string formats the start and end time. - * See {@link DateTime#toFormat} for details. - * @param {Object} opts - Options. - * @param {string} [opts.separator = ' – '] - A separator to place between the start and end - * representations. - * @return {string} - */ - toFormat(dateFormat, { separator = ' – ' } = {}) { - if (!this.isValid) return INVALID$1 - return `${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat( - dateFormat - )}` - } - - /** - * Return a Duration representing the time spanned by this interval. - * @param {string|string[]} [unit=['milliseconds']] - the unit or units (such as 'hours' or 'days') to include in the duration. - * @param {Object} opts - options that affect the creation of the Duration - * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use - * @example Interval.fromDateTimes(dt1, dt2).toDuration().toObject() //=> { milliseconds: 88489257 } - * @example Interval.fromDateTimes(dt1, dt2).toDuration('days').toObject() //=> { days: 1.0241812152777778 } - * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes']).toObject() //=> { hours: 24, minutes: 34.82095 } - * @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes', 'seconds']).toObject() //=> { hours: 24, minutes: 34, seconds: 49.257 } - * @example Interval.fromDateTimes(dt1, dt2).toDuration('seconds').toObject() //=> { seconds: 88489.257 } - * @return {Duration} - */ - toDuration(unit, opts) { - if (!this.isValid) { - return Duration.invalid(this.invalidReason) - } - return this.e.diff(this.s, unit, opts) - } - - /** - * Run mapFn on the interval start and end, returning a new Interval from the resulting DateTimes - * @param {function} mapFn - * @return {Interval} - * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.toUTC()) - * @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.plus({ hours: 2 })) - */ - mapEndpoints(mapFn) { - return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e)) - } -} - -/** - * The Info class contains static methods for retrieving general time and date related data. For example, it has methods for finding out if a time zone has a DST, for listing the months in any supported locale, and for discovering which of Luxon features are available in the current environment. - */ -class Info { - /** - * Return whether the specified zone contains a DST. - * @param {string|Zone} [zone='local'] - Zone to check. Defaults to the environment's local zone. - * @return {boolean} - */ - static hasDST(zone = Settings.defaultZone) { - const proto = DateTime.now().setZone(zone).set({ month: 12 }) - - return !zone.isUniversal && proto.offset !== proto.set({ month: 6 }).offset - } - - /** - * Return whether the specified zone is a valid IANA specifier. - * @param {string} zone - Zone to check - * @return {boolean} - */ - static isValidIANAZone(zone) { - return IANAZone.isValidZone(zone) - } - - /** - * Converts the input into a {@link Zone} instance. - * - * * If `input` is already a Zone instance, it is returned unchanged. - * * If `input` is a string containing a valid time zone name, a Zone instance - * with that name is returned. - * * If `input` is a string that doesn't refer to a known time zone, a Zone - * instance with {@link Zone#isValid} == false is returned. - * * If `input is a number, a Zone instance with the specified fixed offset - * in minutes is returned. - * * If `input` is `null` or `undefined`, the default zone is returned. - * @param {string|Zone|number} [input] - the value to be converted - * @return {Zone} - */ - static normalizeZone(input) { - return normalizeZone(input, Settings.defaultZone) - } - - /** - * Get the weekday on which the week starts according to the given locale. - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @param {string} [opts.locObj=null] - an existing locale object to use - * @returns {number} the start of the week, 1 for Monday through 7 for Sunday - */ - static getStartOfWeek({ locale = null, locObj = null } = {}) { - return (locObj || Locale.create(locale)).getStartOfWeek() - } - - /** - * Get the minimum number of days necessary in a week before it is considered part of the next year according - * to the given locale. - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @param {string} [opts.locObj=null] - an existing locale object to use - * @returns {number} - */ - static getMinimumDaysInFirstWeek({ locale = null, locObj = null } = {}) { - return (locObj || Locale.create(locale)).getMinDaysInFirstWeek() - } - - /** - * Get the weekdays, which are considered the weekend according to the given locale - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @param {string} [opts.locObj=null] - an existing locale object to use - * @returns {number[]} an array of weekdays, 1 for Monday through 7 for Sunday - */ - static getWeekendWeekdays({ locale = null, locObj = null } = {}) { - // copy the array, because we cache it internally - return (locObj || Locale.create(locale)).getWeekendDays().slice() - } - - /** - * Return an array of standalone month names. - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat - * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long" - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @param {string} [opts.numberingSystem=null] - the numbering system - * @param {string} [opts.locObj=null] - an existing locale object to use - * @param {string} [opts.outputCalendar='gregory'] - the calendar - * @example Info.months()[0] //=> 'January' - * @example Info.months('short')[0] //=> 'Jan' - * @example Info.months('numeric')[0] //=> '1' - * @example Info.months('short', { locale: 'fr-CA' } )[0] //=> 'janv.' - * @example Info.months('numeric', { locale: 'ar' })[0] //=> '١' - * @example Info.months('long', { outputCalendar: 'islamic' })[0] //=> 'Rabiʻ I' - * @return {Array} - */ - static months( - length = 'long', - { - locale = null, - numberingSystem = null, - locObj = null, - outputCalendar = 'gregory', - } = {} - ) { - return ( - locObj || Locale.create(locale, numberingSystem, outputCalendar) - ).months(length) - } - - /** - * Return an array of format month names. - * Format months differ from standalone months in that they're meant to appear next to the day of the month. In some languages, that - * changes the string. - * See {@link Info#months} - * @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long" - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @param {string} [opts.numberingSystem=null] - the numbering system - * @param {string} [opts.locObj=null] - an existing locale object to use - * @param {string} [opts.outputCalendar='gregory'] - the calendar - * @return {Array} - */ - static monthsFormat( - length = 'long', - { - locale = null, - numberingSystem = null, - locObj = null, - outputCalendar = 'gregory', - } = {} - ) { - return ( - locObj || Locale.create(locale, numberingSystem, outputCalendar) - ).months(length, true) - } - - /** - * Return an array of standalone week names. - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat - * @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long". - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @param {string} [opts.numberingSystem=null] - the numbering system - * @param {string} [opts.locObj=null] - an existing locale object to use - * @example Info.weekdays()[0] //=> 'Monday' - * @example Info.weekdays('short')[0] //=> 'Mon' - * @example Info.weekdays('short', { locale: 'fr-CA' })[0] //=> 'lun.' - * @example Info.weekdays('short', { locale: 'ar' })[0] //=> 'الاثنين' - * @return {Array} - */ - static weekdays( - length = 'long', - { locale = null, numberingSystem = null, locObj = null } = {} - ) { - return (locObj || Locale.create(locale, numberingSystem, null)).weekdays( - length - ) - } - - /** - * Return an array of format week names. - * Format weekdays differ from standalone weekdays in that they're meant to appear next to more date information. In some languages, that - * changes the string. - * See {@link Info#weekdays} - * @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long". - * @param {Object} opts - options - * @param {string} [opts.locale=null] - the locale code - * @param {string} [opts.numberingSystem=null] - the numbering system - * @param {string} [opts.locObj=null] - an existing locale object to use - * @return {Array} - */ - static weekdaysFormat( - length = 'long', - { locale = null, numberingSystem = null, locObj = null } = {} - ) { - return (locObj || Locale.create(locale, numberingSystem, null)).weekdays( - length, - true - ) - } - - /** - * Return an array of meridiems. - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @example Info.meridiems() //=> [ 'AM', 'PM' ] - * @example Info.meridiems({ locale: 'my' }) //=> [ 'နံနက်', 'ညနေ' ] - * @return {Array} - */ - static meridiems({ locale = null } = {}) { - return Locale.create(locale).meridiems() - } - - /** - * Return an array of eras, such as ['BC', 'AD']. The locale can be specified, but the calendar system is always Gregorian. - * @param {string} [length='short'] - the length of the era representation, such as "short" or "long". - * @param {Object} opts - options - * @param {string} [opts.locale] - the locale code - * @example Info.eras() //=> [ 'BC', 'AD' ] - * @example Info.eras('long') //=> [ 'Before Christ', 'Anno Domini' ] - * @example Info.eras('long', { locale: 'fr' }) //=> [ 'avant Jésus-Christ', 'après Jésus-Christ' ] - * @return {Array} - */ - static eras(length = 'short', { locale = null } = {}) { - return Locale.create(locale, null, 'gregory').eras(length) - } - - /** - * Return the set of available features in this environment. - * Some features of Luxon are not available in all environments. For example, on older browsers, relative time formatting support is not available. Use this function to figure out if that's the case. - * Keys: - * * `relative`: whether this environment supports relative time formatting - * * `localeWeek`: whether this environment supports different weekdays for the start of the week based on the locale - * @example Info.features() //=> { relative: false, localeWeek: true } - * @return {Object} - */ - static features() { - return { relative: hasRelative(), localeWeek: hasLocaleWeekInfo() } - } -} - -function dayDiff(earlier, later) { - const utcDayStart = (dt) => - dt.toUTC(0, { keepLocalTime: true }).startOf('day').valueOf(), - ms = utcDayStart(later) - utcDayStart(earlier) - return Math.floor(Duration.fromMillis(ms).as('days')) -} - -function highOrderDiffs(cursor, later, units) { - const differs = [ - ['years', (a, b) => b.year - a.year], - ['quarters', (a, b) => b.quarter - a.quarter + (b.year - a.year) * 4], - ['months', (a, b) => b.month - a.month + (b.year - a.year) * 12], - [ - 'weeks', - (a, b) => { - const days = dayDiff(a, b) - return (days - (days % 7)) / 7 - }, - ], - ['days', dayDiff], - ] - - const results = {} - const earlier = cursor - let lowestOrder, highWater - - /* This loop tries to diff using larger units first. - If we overshoot, we backtrack and try the next smaller unit. - "cursor" starts out at the earlier timestamp and moves closer and closer to "later" - as we use smaller and smaller units. - highWater keeps track of where we would be if we added one more of the smallest unit, - this is used later to potentially convert any difference smaller than the smallest higher order unit - into a fraction of that smallest higher order unit - */ - for (const [unit, differ] of differs) { - if (units.indexOf(unit) >= 0) { - lowestOrder = unit - - results[unit] = differ(cursor, later) - highWater = earlier.plus(results) - - if (highWater > later) { - // we overshot the end point, backtrack cursor by 1 - results[unit]-- - cursor = earlier.plus(results) - - // if we are still overshooting now, we need to backtrack again - // this happens in certain situations when diffing times in different zones, - // because this calculation ignores time zones - if (cursor > later) { - // keep the "overshot by 1" around as highWater - highWater = cursor - // backtrack cursor by 1 - results[unit]-- - cursor = earlier.plus(results) - } - } else { - cursor = highWater - } - } - } - - return [cursor, results, highWater, lowestOrder] -} - -function diff(earlier, later, units, opts) { - let [cursor, results, highWater, lowestOrder] = highOrderDiffs( - earlier, - later, - units - ) - - const remainingMillis = later - cursor - - const lowerOrderUnits = units.filter( - (u) => ['hours', 'minutes', 'seconds', 'milliseconds'].indexOf(u) >= 0 - ) - - if (lowerOrderUnits.length === 0) { - if (highWater < later) { - highWater = cursor.plus({ [lowestOrder]: 1 }) - } - - if (highWater !== cursor) { - results[lowestOrder] = - (results[lowestOrder] || 0) + remainingMillis / (highWater - cursor) - } - } - - const duration = Duration.fromObject(results, opts) - - if (lowerOrderUnits.length > 0) { - return Duration.fromMillis(remainingMillis, opts) - .shiftTo(...lowerOrderUnits) - .plus(duration) - } else { - return duration - } -} - -const numberingSystems = { - arab: '[\u0660-\u0669]', - arabext: '[\u06F0-\u06F9]', - bali: '[\u1B50-\u1B59]', - beng: '[\u09E6-\u09EF]', - deva: '[\u0966-\u096F]', - fullwide: '[\uFF10-\uFF19]', - gujr: '[\u0AE6-\u0AEF]', - hanidec: '[〇|一|二|三|四|五|六|七|八|九]', - khmr: '[\u17E0-\u17E9]', - knda: '[\u0CE6-\u0CEF]', - laoo: '[\u0ED0-\u0ED9]', - limb: '[\u1946-\u194F]', - mlym: '[\u0D66-\u0D6F]', - mong: '[\u1810-\u1819]', - mymr: '[\u1040-\u1049]', - orya: '[\u0B66-\u0B6F]', - tamldec: '[\u0BE6-\u0BEF]', - telu: '[\u0C66-\u0C6F]', - thai: '[\u0E50-\u0E59]', - tibt: '[\u0F20-\u0F29]', - latn: '\\d', -} - -const numberingSystemsUTF16 = { - arab: [1632, 1641], - arabext: [1776, 1785], - bali: [6992, 7001], - beng: [2534, 2543], - deva: [2406, 2415], - fullwide: [65296, 65303], - gujr: [2790, 2799], - khmr: [6112, 6121], - knda: [3302, 3311], - laoo: [3792, 3801], - limb: [6470, 6479], - mlym: [3430, 3439], - mong: [6160, 6169], - mymr: [4160, 4169], - orya: [2918, 2927], - tamldec: [3046, 3055], - telu: [3174, 3183], - thai: [3664, 3673], - tibt: [3872, 3881], -} - -const hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, '').split('') - -function parseDigits(str) { - let value = parseInt(str, 10) - if (isNaN(value)) { - value = '' - for (let i = 0; i < str.length; i++) { - const code = str.charCodeAt(i) - - if (str[i].search(numberingSystems.hanidec) !== -1) { - value += hanidecChars.indexOf(str[i]) - } else { - for (const key in numberingSystemsUTF16) { - const [min, max] = numberingSystemsUTF16[key] - if (code >= min && code <= max) { - value += code - min - } - } - } - } - return parseInt(value, 10) - } else { - return value - } -} - -function digitRegex({ numberingSystem }, append = '') { - return new RegExp(`${numberingSystems[numberingSystem || 'latn']}${append}`) -} - -const MISSING_FTP = 'missing Intl.DateTimeFormat.formatToParts support' - -function intUnit(regex, post = (i) => i) { - return { regex, deser: ([s]) => post(parseDigits(s)) } -} - -const NBSP = String.fromCharCode(160) -const spaceOrNBSP = `[ ${NBSP}]` -const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, 'g') - -function fixListRegex(s) { - // make dots optional and also make them literal - // make space and non breakable space characters interchangeable - return s.replace(/\./g, '\\.?').replace(spaceOrNBSPRegExp, spaceOrNBSP) -} - -function stripInsensitivities(s) { - return s - .replace(/\./g, '') // ignore dots that were made optional - .replace(spaceOrNBSPRegExp, ' ') // interchange space and nbsp - .toLowerCase() -} - -function oneOf(strings, startIndex) { - if (strings === null) { - return null - } else { - return { - regex: RegExp(strings.map(fixListRegex).join('|')), - deser: ([s]) => - strings.findIndex( - (i) => stripInsensitivities(s) === stripInsensitivities(i) - ) + startIndex, - } - } -} - -function offset(regex, groups) { - return { regex, deser: ([, h, m]) => signedOffset(h, m), groups } -} - -function simple(regex) { - return { regex, deser: ([s]) => s } -} - -function escapeToken(value) { - return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') -} - -/** - * @param token - * @param {Locale} loc - */ -function unitForToken(token, loc) { - const one = digitRegex(loc), - two = digitRegex(loc, '{2}'), - three = digitRegex(loc, '{3}'), - four = digitRegex(loc, '{4}'), - six = digitRegex(loc, '{6}'), - oneOrTwo = digitRegex(loc, '{1,2}'), - oneToThree = digitRegex(loc, '{1,3}'), - oneToSix = digitRegex(loc, '{1,6}'), - oneToNine = digitRegex(loc, '{1,9}'), - twoToFour = digitRegex(loc, '{2,4}'), - fourToSix = digitRegex(loc, '{4,6}'), - literal = (t) => ({ - regex: RegExp(escapeToken(t.val)), - deser: ([s]) => s, - literal: true, - }), - unitate = (t) => { - if (token.literal) { - return literal(t) - } - switch (t.val) { - // era - case 'G': - return oneOf(loc.eras('short'), 0) - case 'GG': - return oneOf(loc.eras('long'), 0) - // years - case 'y': - return intUnit(oneToSix) - case 'yy': - return intUnit(twoToFour, untruncateYear) - case 'yyyy': - return intUnit(four) - case 'yyyyy': - return intUnit(fourToSix) - case 'yyyyyy': - return intUnit(six) - // months - case 'M': - return intUnit(oneOrTwo) - case 'MM': - return intUnit(two) - case 'MMM': - return oneOf(loc.months('short', true), 1) - case 'MMMM': - return oneOf(loc.months('long', true), 1) - case 'L': - return intUnit(oneOrTwo) - case 'LL': - return intUnit(two) - case 'LLL': - return oneOf(loc.months('short', false), 1) - case 'LLLL': - return oneOf(loc.months('long', false), 1) - // dates - case 'd': - return intUnit(oneOrTwo) - case 'dd': - return intUnit(two) - // ordinals - case 'o': - return intUnit(oneToThree) - case 'ooo': - return intUnit(three) - // time - case 'HH': - return intUnit(two) - case 'H': - return intUnit(oneOrTwo) - case 'hh': - return intUnit(two) - case 'h': - return intUnit(oneOrTwo) - case 'mm': - return intUnit(two) - case 'm': - return intUnit(oneOrTwo) - case 'q': - return intUnit(oneOrTwo) - case 'qq': - return intUnit(two) - case 's': - return intUnit(oneOrTwo) - case 'ss': - return intUnit(two) - case 'S': - return intUnit(oneToThree) - case 'SSS': - return intUnit(three) - case 'u': - return simple(oneToNine) - case 'uu': - return simple(oneOrTwo) - case 'uuu': - return intUnit(one) - // meridiem - case 'a': - return oneOf(loc.meridiems(), 0) - // weekYear (k) - case 'kkkk': - return intUnit(four) - case 'kk': - return intUnit(twoToFour, untruncateYear) - // weekNumber (W) - case 'W': - return intUnit(oneOrTwo) - case 'WW': - return intUnit(two) - // weekdays - case 'E': - case 'c': - return intUnit(one) - case 'EEE': - return oneOf(loc.weekdays('short', false), 1) - case 'EEEE': - return oneOf(loc.weekdays('long', false), 1) - case 'ccc': - return oneOf(loc.weekdays('short', true), 1) - case 'cccc': - return oneOf(loc.weekdays('long', true), 1) - // offset/zone - case 'Z': - case 'ZZ': - return offset( - new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`), - 2 - ) - case 'ZZZ': - return offset( - new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`), - 2 - ) - // we don't support ZZZZ (PST) or ZZZZZ (Pacific Standard Time) in parsing - // because we don't have any way to figure out what they are - case 'z': - return simple(/[a-z_+-/]{1,256}?/i) - // this special-case "token" represents a place where a macro-token expanded into a white-space literal - // in this case we accept any non-newline white-space - case ' ': - return simple(/[^\S\n\r]/) - default: - return literal(t) - } - } - - const unit = unitate(token) || { - invalidReason: MISSING_FTP, - } - - unit.token = token - - return unit -} - -const partTypeStyleToTokenVal = { - year: { - '2-digit': 'yy', - numeric: 'yyyyy', - }, - month: { - numeric: 'M', - '2-digit': 'MM', - short: 'MMM', - long: 'MMMM', - }, - day: { - numeric: 'd', - '2-digit': 'dd', - }, - weekday: { - short: 'EEE', - long: 'EEEE', - }, - dayperiod: 'a', - dayPeriod: 'a', - hour12: { - numeric: 'h', - '2-digit': 'hh', - }, - hour24: { - numeric: 'H', - '2-digit': 'HH', - }, - minute: { - numeric: 'm', - '2-digit': 'mm', - }, - second: { - numeric: 's', - '2-digit': 'ss', - }, - timeZoneName: { - long: 'ZZZZZ', - short: 'ZZZ', - }, -} - -function tokenForPart(part, formatOpts, resolvedOpts) { - const { type, value } = part - - if (type === 'literal') { - const isSpace = /^\s+$/.test(value) - return { - literal: !isSpace, - val: isSpace ? ' ' : value, - } - } - - const style = formatOpts[type] - - // The user might have explicitly specified hour12 or hourCycle - // if so, respect their decision - // if not, refer back to the resolvedOpts, which are based on the locale - let actualType = type - if (type === 'hour') { - if (formatOpts.hour12 != null) { - actualType = formatOpts.hour12 ? 'hour12' : 'hour24' - } else if (formatOpts.hourCycle != null) { - if (formatOpts.hourCycle === 'h11' || formatOpts.hourCycle === 'h12') { - actualType = 'hour12' - } else { - actualType = 'hour24' - } - } else { - // tokens only differentiate between 24 hours or not, - // so we do not need to check hourCycle here, which is less supported anyways - actualType = resolvedOpts.hour12 ? 'hour12' : 'hour24' - } - } - let val = partTypeStyleToTokenVal[actualType] - if (typeof val === 'object') { - val = val[style] - } - - if (val) { - return { - literal: false, - val, - } - } - - return undefined -} - -function buildRegex(units) { - const re = units.map((u) => u.regex).reduce((f, r) => `${f}(${r.source})`, '') - return [`^${re}$`, units] -} - -function match(input, regex, handlers) { - const matches = input.match(regex) - - if (matches) { - const all = {} - let matchIndex = 1 - for (const i in handlers) { - if (hasOwnProperty(handlers, i)) { - const h = handlers[i], - groups = h.groups ? h.groups + 1 : 1 - if (!h.literal && h.token) { - all[h.token.val[0]] = h.deser( - matches.slice(matchIndex, matchIndex + groups) - ) - } - matchIndex += groups - } - } - return [matches, all] - } else { - return [matches, {}] - } -} - -function dateTimeFromMatches(matches) { - const toField = (token) => { - switch (token) { - case 'S': - return 'millisecond' - case 's': - return 'second' - case 'm': - return 'minute' - case 'h': - case 'H': - return 'hour' - case 'd': - return 'day' - case 'o': - return 'ordinal' - case 'L': - case 'M': - return 'month' - case 'y': - return 'year' - case 'E': - case 'c': - return 'weekday' - case 'W': - return 'weekNumber' - case 'k': - return 'weekYear' - case 'q': - return 'quarter' - default: - return null - } - } - - let zone = null - let specificOffset - if (!isUndefined(matches.z)) { - zone = IANAZone.create(matches.z) - } - - if (!isUndefined(matches.Z)) { - if (!zone) { - zone = new FixedOffsetZone(matches.Z) - } - specificOffset = matches.Z - } - - if (!isUndefined(matches.q)) { - matches.M = (matches.q - 1) * 3 + 1 - } - - if (!isUndefined(matches.h)) { - if (matches.h < 12 && matches.a === 1) { - matches.h += 12 - } else if (matches.h === 12 && matches.a === 0) { - matches.h = 0 - } - } - - if (matches.G === 0 && matches.y) { - matches.y = -matches.y - } - - if (!isUndefined(matches.u)) { - matches.S = parseMillis(matches.u) - } - - const vals = Object.keys(matches).reduce((r, k) => { - const f = toField(k) - if (f) { - r[f] = matches[k] - } - - return r - }, {}) - - return [vals, zone, specificOffset] -} - -let dummyDateTimeCache = null - -function getDummyDateTime() { - if (!dummyDateTimeCache) { - dummyDateTimeCache = DateTime.fromMillis(1555555555555) - } - - return dummyDateTimeCache -} - -function maybeExpandMacroToken(token, locale) { - if (token.literal) { - return token - } - - const formatOpts = Formatter.macroTokenToFormatOpts(token.val) - const tokens = formatOptsToTokens(formatOpts, locale) - - if (tokens == null || tokens.includes(undefined)) { - return token - } - - return tokens -} - -function expandMacroTokens(tokens, locale) { - return Array.prototype.concat( - ...tokens.map((t) => maybeExpandMacroToken(t, locale)) - ) -} - -/** - * @private - */ - -function explainFromTokens(locale, input, format) { - const tokens = expandMacroTokens(Formatter.parseFormat(format), locale), - units = tokens.map((t) => unitForToken(t, locale)), - disqualifyingUnit = units.find((t) => t.invalidReason) - - if (disqualifyingUnit) { - return { input, tokens, invalidReason: disqualifyingUnit.invalidReason } - } else { - const [regexString, handlers] = buildRegex(units), - regex = RegExp(regexString, 'i'), - [rawMatches, matches] = match(input, regex, handlers), - [result, zone, specificOffset] = matches - ? dateTimeFromMatches(matches) - : [null, null, undefined] - if (hasOwnProperty(matches, 'a') && hasOwnProperty(matches, 'H')) { - throw new ConflictingSpecificationError( - "Can't include meridiem when specifying 24-hour format" - ) - } - return { - input, - tokens, - regex, - rawMatches, - matches, - result, - zone, - specificOffset, - } - } -} - -function parseFromTokens(locale, input, format) { - const { result, zone, specificOffset, invalidReason } = explainFromTokens( - locale, - input, - format - ) - return [result, zone, specificOffset, invalidReason] -} - -function formatOptsToTokens(formatOpts, locale) { - if (!formatOpts) { - return null - } - - const formatter = Formatter.create(locale, formatOpts) - const df = formatter.dtFormatter(getDummyDateTime()) - const parts = df.formatToParts() - const resolvedOpts = df.resolvedOptions() - return parts.map((p) => tokenForPart(p, formatOpts, resolvedOpts)) -} - -const INVALID = 'Invalid DateTime' -const MAX_DATE = 8.64e15 - -function unsupportedZone(zone) { - return new Invalid( - 'unsupported zone', - `the zone "${zone.name}" is not supported` - ) -} - -// we cache week data on the DT object and this intermediates the cache -/** - * @param {DateTime} dt - */ -function possiblyCachedWeekData(dt) { - if (dt.weekData === null) { - dt.weekData = gregorianToWeek(dt.c) - } - return dt.weekData -} - -/** - * @param {DateTime} dt - */ -function possiblyCachedLocalWeekData(dt) { - if (dt.localWeekData === null) { - dt.localWeekData = gregorianToWeek( - dt.c, - dt.loc.getMinDaysInFirstWeek(), - dt.loc.getStartOfWeek() - ) - } - return dt.localWeekData -} - -// clone really means, "make a new object with these modifications". all "setters" really use this -// to create a new object while only changing some of the properties -function clone(inst, alts) { - const current = { - ts: inst.ts, - zone: inst.zone, - c: inst.c, - o: inst.o, - loc: inst.loc, - invalid: inst.invalid, - } - return new DateTime({ ...current, ...alts, old: current }) -} - -// find the right offset a given local time. The o input is our guess, which determines which -// offset we'll pick in ambiguous cases (e.g. there are two 3 AMs b/c Fallback DST) -function fixOffset(localTS, o, tz) { - // Our UTC time is just a guess because our offset is just a guess - let utcGuess = localTS - o * 60 * 1000 - - // Test whether the zone matches the offset for this ts - const o2 = tz.offset(utcGuess) - - // If so, offset didn't change and we're done - if (o === o2) { - return [utcGuess, o] - } - - // If not, change the ts by the difference in the offset - utcGuess -= (o2 - o) * 60 * 1000 - - // If that gives us the local time we want, we're done - const o3 = tz.offset(utcGuess) - if (o2 === o3) { - return [utcGuess, o2] - } - - // If it's different, we're in a hole time. The offset has changed, but the we don't adjust the time - return [localTS - Math.min(o2, o3) * 60 * 1000, Math.max(o2, o3)] -} - -// convert an epoch timestamp into a calendar object with the given offset -function tsToObj(ts, offset) { - ts += offset * 60 * 1000 - - const d = new Date(ts) - - return { - year: d.getUTCFullYear(), - month: d.getUTCMonth() + 1, - day: d.getUTCDate(), - hour: d.getUTCHours(), - minute: d.getUTCMinutes(), - second: d.getUTCSeconds(), - millisecond: d.getUTCMilliseconds(), - } -} - -// convert a calendar object to a epoch timestamp -function objToTS(obj, offset, zone) { - return fixOffset(objToLocalTS(obj), offset, zone) -} - -// create a new DT instance by adding a duration, adjusting for DSTs -function adjustTime(inst, dur) { - const oPre = inst.o, - year = inst.c.year + Math.trunc(dur.years), - month = - inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, - c = { - ...inst.c, - year, - month, - day: - Math.min(inst.c.day, daysInMonth(year, month)) + - Math.trunc(dur.days) + - Math.trunc(dur.weeks) * 7, - }, - millisToAdd = Duration.fromObject({ - years: dur.years - Math.trunc(dur.years), - quarters: dur.quarters - Math.trunc(dur.quarters), - months: dur.months - Math.trunc(dur.months), - weeks: dur.weeks - Math.trunc(dur.weeks), - days: dur.days - Math.trunc(dur.days), - hours: dur.hours, - minutes: dur.minutes, - seconds: dur.seconds, - milliseconds: dur.milliseconds, - }).as('milliseconds'), - localTS = objToLocalTS(c) - - let [ts, o] = fixOffset(localTS, oPre, inst.zone) - - if (millisToAdd !== 0) { - ts += millisToAdd - // that could have changed the offset by going over a DST, but we want to keep the ts the same - o = inst.zone.offset(ts) - } - - return { ts, o } -} - -// helper useful in turning the results of parsing into real dates -// by handling the zone options -function parseDataToDateTime( - parsed, - parsedZone, - opts, - format, - text, - specificOffset -) { - const { setZone, zone } = opts - if ((parsed && Object.keys(parsed).length !== 0) || parsedZone) { - const interpretationZone = parsedZone || zone, - inst = DateTime.fromObject(parsed, { - ...opts, - zone: interpretationZone, - specificOffset, - }) - return setZone ? inst : inst.setZone(zone) - } else { - return DateTime.invalid( - new Invalid( - 'unparsable', - `the input "${text}" can't be parsed as ${format}` - ) - ) - } -} - -// if you want to output a technical format (e.g. RFC 2822), this helper -// helps handle the details -function toTechFormat(dt, format, allowZ = true) { - return dt.isValid - ? Formatter.create(Locale.create('en-US'), { - allowZ, - forceSimple: true, - }).formatDateTimeFromString(dt, format) - : null -} - -function toISODate(o, extended) { - const longFormat = o.c.year > 9999 || o.c.year < 0 - let c = '' - if (longFormat && o.c.year >= 0) c += '+' - c += padStart(o.c.year, longFormat ? 6 : 4) - - if (extended) { - c += '-' - c += padStart(o.c.month) - c += '-' - c += padStart(o.c.day) - } else { - c += padStart(o.c.month) - c += padStart(o.c.day) - } - return c -} - -function toISOTime( - o, - extended, - suppressSeconds, - suppressMilliseconds, - includeOffset, - extendedZone -) { - let c = padStart(o.c.hour) - if (extended) { - c += ':' - c += padStart(o.c.minute) - if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) { - c += ':' - } - } else { - c += padStart(o.c.minute) - } - - if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) { - c += padStart(o.c.second) - - if (o.c.millisecond !== 0 || !suppressMilliseconds) { - c += '.' - c += padStart(o.c.millisecond, 3) - } - } - - if (includeOffset) { - if (o.isOffsetFixed && o.offset === 0 && !extendedZone) { - c += 'Z' - } else if (o.o < 0) { - c += '-' - c += padStart(Math.trunc(-o.o / 60)) - c += ':' - c += padStart(Math.trunc(-o.o % 60)) - } else { - c += '+' - c += padStart(Math.trunc(o.o / 60)) - c += ':' - c += padStart(Math.trunc(o.o % 60)) - } - } - - if (extendedZone) { - c += '[' + o.zone.ianaName + ']' - } - return c -} - -// defaults for unspecified units in the supported calendars -const defaultUnitValues = { - month: 1, - day: 1, - hour: 0, - minute: 0, - second: 0, - millisecond: 0, - }, - defaultWeekUnitValues = { - weekNumber: 1, - weekday: 1, - hour: 0, - minute: 0, - second: 0, - millisecond: 0, - }, - defaultOrdinalUnitValues = { - ordinal: 1, - hour: 0, - minute: 0, - second: 0, - millisecond: 0, - } - -// Units in the supported calendars, sorted by bigness -const orderedUnits = [ - 'year', - 'month', - 'day', - 'hour', - 'minute', - 'second', - 'millisecond', - ], - orderedWeekUnits = [ - 'weekYear', - 'weekNumber', - 'weekday', - 'hour', - 'minute', - 'second', - 'millisecond', - ], - orderedOrdinalUnits = [ - 'year', - 'ordinal', - 'hour', - 'minute', - 'second', - 'millisecond', - ] - -// standardize case and plurality in units -function normalizeUnit(unit) { - const normalized = { - year: 'year', - years: 'year', - month: 'month', - months: 'month', - day: 'day', - days: 'day', - hour: 'hour', - hours: 'hour', - minute: 'minute', - minutes: 'minute', - quarter: 'quarter', - quarters: 'quarter', - second: 'second', - seconds: 'second', - millisecond: 'millisecond', - milliseconds: 'millisecond', - weekday: 'weekday', - weekdays: 'weekday', - weeknumber: 'weekNumber', - weeksnumber: 'weekNumber', - weeknumbers: 'weekNumber', - weekyear: 'weekYear', - weekyears: 'weekYear', - ordinal: 'ordinal', - }[unit.toLowerCase()] - - if (!normalized) throw new InvalidUnitError(unit) - - return normalized -} - -function normalizeUnitWithLocalWeeks(unit) { - switch (unit.toLowerCase()) { - case 'localweekday': - case 'localweekdays': - return 'localWeekday' - case 'localweeknumber': - case 'localweeknumbers': - return 'localWeekNumber' - case 'localweekyear': - case 'localweekyears': - return 'localWeekYear' - default: - return normalizeUnit(unit) - } -} - -// this is a dumbed down version of fromObject() that runs about 60% faster -// but doesn't do any validation, makes a bunch of assumptions about what units -// are present, and so on. -function quickDT(obj, opts) { - const zone = normalizeZone(opts.zone, Settings.defaultZone), - loc = Locale.fromObject(opts), - tsNow = Settings.now() - - let ts, o - - // assume we have the higher-order units - if (!isUndefined(obj.year)) { - for (const u of orderedUnits) { - if (isUndefined(obj[u])) { - obj[u] = defaultUnitValues[u] - } - } - - const invalid = hasInvalidGregorianData(obj) || hasInvalidTimeData(obj) - if (invalid) { - return DateTime.invalid(invalid) - } - - const offsetProvis = zone.offset(tsNow) - ;[ts, o] = objToTS(obj, offsetProvis, zone) - } else { - ts = tsNow - } - - return new DateTime({ ts, zone, loc, o }) -} - -function diffRelative(start, end, opts) { - const round = isUndefined(opts.round) ? true : opts.round, - format = (c, unit) => { - c = roundTo(c, round || opts.calendary ? 0 : 2, true) - const formatter = end.loc.clone(opts).relFormatter(opts) - return formatter.format(c, unit) - }, - differ = (unit) => { - if (opts.calendary) { - if (!end.hasSame(start, unit)) { - return end.startOf(unit).diff(start.startOf(unit), unit).get(unit) - } else return 0 - } else { - return end.diff(start, unit).get(unit) - } - } - - if (opts.unit) { - return format(differ(opts.unit), opts.unit) - } - - for (const unit of opts.units) { - const count = differ(unit) - if (Math.abs(count) >= 1) { - return format(count, unit) - } - } - return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]) -} - -function lastOpts(argList) { - let opts = {}, - args - if (argList.length > 0 && typeof argList[argList.length - 1] === 'object') { - opts = argList[argList.length - 1] - args = Array.from(argList).slice(0, argList.length - 1) - } else { - args = Array.from(argList) - } - return [opts, args] -} - -/** - * A DateTime is an immutable data structure representing a specific date and time and accompanying methods. It contains class and instance methods for creating, parsing, interrogating, transforming, and formatting them. - * - * A DateTime comprises of: - * * A timestamp. Each DateTime instance refers to a specific millisecond of the Unix epoch. - * * A time zone. Each instance is considered in the context of a specific zone (by default the local system's zone). - * * Configuration properties that effect how output strings are formatted, such as `locale`, `numberingSystem`, and `outputCalendar`. - * - * Here is a brief overview of the most commonly used functionality it provides: - * - * * **Creation**: To create a DateTime from its components, use one of its factory class methods: {@link DateTime.local}, {@link DateTime.utc}, and (most flexibly) {@link DateTime.fromObject}. To create one from a standard string format, use {@link DateTime.fromISO}, {@link DateTime.fromHTTP}, and {@link DateTime.fromRFC2822}. To create one from a custom string format, use {@link DateTime.fromFormat}. To create one from a native JS date, use {@link DateTime.fromJSDate}. - * * **Gregorian calendar and time**: To examine the Gregorian properties of a DateTime individually (i.e as opposed to collectively through {@link DateTime#toObject}), use the {@link DateTime#year}, {@link DateTime#month}, - * {@link DateTime#day}, {@link DateTime#hour}, {@link DateTime#minute}, {@link DateTime#second}, {@link DateTime#millisecond} accessors. - * * **Week calendar**: For ISO week calendar attributes, see the {@link DateTime#weekYear}, {@link DateTime#weekNumber}, and {@link DateTime#weekday} accessors. - * * **Configuration** See the {@link DateTime#locale} and {@link DateTime#numberingSystem} accessors. - * * **Transformation**: To transform the DateTime into other DateTimes, use {@link DateTime#set}, {@link DateTime#reconfigure}, {@link DateTime#setZone}, {@link DateTime#setLocale}, {@link DateTime.plus}, {@link DateTime#minus}, {@link DateTime#endOf}, {@link DateTime#startOf}, {@link DateTime#toUTC}, and {@link DateTime#toLocal}. - * * **Output**: To convert the DateTime to other representations, use the {@link DateTime#toRelative}, {@link DateTime#toRelativeCalendar}, {@link DateTime#toJSON}, {@link DateTime#toISO}, {@link DateTime#toHTTP}, {@link DateTime#toObject}, {@link DateTime#toRFC2822}, {@link DateTime#toString}, {@link DateTime#toLocaleString}, {@link DateTime#toFormat}, {@link DateTime#toMillis} and {@link DateTime#toJSDate}. - * - * There's plenty others documented below. In addition, for more information on subtler topics like internationalization, time zones, alternative calendars, validity, and so on, see the external documentation. - */ -class DateTime { - /** - * @access private - */ - constructor(config) { - const zone = config.zone || Settings.defaultZone - - let invalid = - config.invalid || - (Number.isNaN(config.ts) ? new Invalid('invalid input') : null) || - (!zone.isValid ? unsupportedZone(zone) : null) - /** - * @access private - */ - this.ts = isUndefined(config.ts) ? Settings.now() : config.ts - - let c = null, - o = null - if (!invalid) { - const unchanged = - config.old && config.old.ts === this.ts && config.old.zone.equals(zone) - - if (unchanged) { - ;[c, o] = [config.old.c, config.old.o] - } else { - const ot = zone.offset(this.ts) - c = tsToObj(this.ts, ot) - invalid = Number.isNaN(c.year) ? new Invalid('invalid input') : null - c = invalid ? null : c - o = invalid ? null : ot - } - } - - /** - * @access private - */ - this._zone = zone - /** - * @access private - */ - this.loc = config.loc || Locale.create() - /** - * @access private - */ - this.invalid = invalid - /** - * @access private - */ - this.weekData = null - /** - * @access private - */ - this.localWeekData = null - /** - * @access private - */ - this.c = c - /** - * @access private - */ - this.o = o - /** - * @access private - */ - this.isLuxonDateTime = true - } - - // CONSTRUCT - - /** - * Create a DateTime for the current instant, in the system's time zone. - * - * Use Settings to override these default values if needed. - * @example DateTime.now().toISO() //~> now in the ISO format - * @return {DateTime} - */ - static now() { - return new DateTime({}) - } - - /** - * Create a local DateTime - * @param {number} [year] - The calendar year. If omitted (as in, call `local()` with no arguments), the current time will be used - * @param {number} [month=1] - The month, 1-indexed - * @param {number} [day=1] - The day of the month, 1-indexed - * @param {number} [hour=0] - The hour of the day, in 24-hour time - * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59 - * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59 - * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999 - * @example DateTime.local() //~> now - * @example DateTime.local({ zone: "America/New_York" }) //~> now, in US east coast time - * @example DateTime.local(2017) //~> 2017-01-01T00:00:00 - * @example DateTime.local(2017, 3) //~> 2017-03-01T00:00:00 - * @example DateTime.local(2017, 3, 12, { locale: "fr" }) //~> 2017-03-12T00:00:00, with a French locale - * @example DateTime.local(2017, 3, 12, 5) //~> 2017-03-12T05:00:00 - * @example DateTime.local(2017, 3, 12, 5, { zone: "utc" }) //~> 2017-03-12T05:00:00, in UTC - * @example DateTime.local(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00 - * @example DateTime.local(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10 - * @example DateTime.local(2017, 3, 12, 5, 45, 10, 765) //~> 2017-03-12T05:45:10.765 - * @return {DateTime} - */ - static local() { - const [opts, args] = lastOpts(arguments), - [year, month, day, hour, minute, second, millisecond] = args - return quickDT( - { year, month, day, hour, minute, second, millisecond }, - opts - ) - } - - /** - * Create a DateTime in UTC - * @param {number} [year] - The calendar year. If omitted (as in, call `utc()` with no arguments), the current time will be used - * @param {number} [month=1] - The month, 1-indexed - * @param {number} [day=1] - The day of the month - * @param {number} [hour=0] - The hour of the day, in 24-hour time - * @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59 - * @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59 - * @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999 - * @param {Object} options - configuration options for the DateTime - * @param {string} [options.locale] - a locale to set on the resulting DateTime instance - * @param {string} [options.outputCalendar] - the output calendar to set on the resulting DateTime instance - * @param {string} [options.numberingSystem] - the numbering system to set on the resulting DateTime instance - * @example DateTime.utc() //~> now - * @example DateTime.utc(2017) //~> 2017-01-01T00:00:00Z - * @example DateTime.utc(2017, 3) //~> 2017-03-01T00:00:00Z - * @example DateTime.utc(2017, 3, 12) //~> 2017-03-12T00:00:00Z - * @example DateTime.utc(2017, 3, 12, 5) //~> 2017-03-12T05:00:00Z - * @example DateTime.utc(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00Z - * @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" }) //~> 2017-03-12T05:45:00Z with a French locale - * @example DateTime.utc(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10Z - * @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr" }) //~> 2017-03-12T05:45:10.765Z with a French locale - * @return {DateTime} - */ - static utc() { - const [opts, args] = lastOpts(arguments), - [year, month, day, hour, minute, second, millisecond] = args - - opts.zone = FixedOffsetZone.utcInstance - return quickDT( - { year, month, day, hour, minute, second, millisecond }, - opts - ) - } - - /** - * Create a DateTime from a JavaScript Date object. Uses the default zone. - * @param {Date} date - a JavaScript Date object - * @param {Object} options - configuration options for the DateTime - * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into - * @return {DateTime} - */ - static fromJSDate(date, options = {}) { - const ts = isDate(date) ? date.valueOf() : NaN - if (Number.isNaN(ts)) { - return DateTime.invalid('invalid input') - } - - const zoneToUse = normalizeZone(options.zone, Settings.defaultZone) - if (!zoneToUse.isValid) { - return DateTime.invalid(unsupportedZone(zoneToUse)) - } - - return new DateTime({ - ts: ts, - zone: zoneToUse, - loc: Locale.fromObject(options), - }) - } - - /** - * Create a DateTime from a number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone. - * @param {number} milliseconds - a number of milliseconds since 1970 UTC - * @param {Object} options - configuration options for the DateTime - * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into - * @param {string} [options.locale] - a locale to set on the resulting DateTime instance - * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance - * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance - * @return {DateTime} - */ - static fromMillis(milliseconds, options = {}) { - if (!isNumber(milliseconds)) { - throw new InvalidArgumentError( - `fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}` - ) - } else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) { - // this isn't perfect because because we can still end up out of range because of additional shifting, but it's a start - return DateTime.invalid('Timestamp out of range') - } else { - return new DateTime({ - ts: milliseconds, - zone: normalizeZone(options.zone, Settings.defaultZone), - loc: Locale.fromObject(options), - }) - } - } - - /** - * Create a DateTime from a number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone. - * @param {number} seconds - a number of seconds since 1970 UTC - * @param {Object} options - configuration options for the DateTime - * @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into - * @param {string} [options.locale] - a locale to set on the resulting DateTime instance - * @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance - * @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance - * @return {DateTime} - */ - static fromSeconds(seconds, options = {}) { - if (!isNumber(seconds)) { - throw new InvalidArgumentError('fromSeconds requires a numerical input') - } else { - return new DateTime({ - ts: seconds * 1000, - zone: normalizeZone(options.zone, Settings.defaultZone), - loc: Locale.fromObject(options), - }) - } - } - - /** - * Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults. - * @param {Object} obj - the object to create the DateTime from - * @param {number} obj.year - a year, such as 1987 - * @param {number} obj.month - a month, 1-12 - * @param {number} obj.day - a day of the month, 1-31, depending on the month - * @param {number} obj.ordinal - day of the year, 1-365 or 366 - * @param {number} obj.weekYear - an ISO week year - * @param {number} obj.weekNumber - an ISO week number, between 1 and 52 or 53, depending on the year - * @param {number} obj.weekday - an ISO weekday, 1-7, where 1 is Monday and 7 is Sunday - * @param {number} obj.localWeekYear - a week year, according to the locale - * @param {number} obj.localWeekNumber - a week number, between 1 and 52 or 53, depending on the year, according to the locale - * @param {number} obj.localWeekday - a weekday, 1-7, where 1 is the first and 7 is the last day of the week, according to the locale - * @param {number} obj.hour - hour of the day, 0-23 - * @param {number} obj.minute - minute of the hour, 0-59 - * @param {number} obj.second - second of the minute, 0-59 - * @param {number} obj.millisecond - millisecond of the second, 0-999 - * @param {Object} opts - options for creating this DateTime - * @param {string|Zone} [opts.zone='local'] - interpret the numbers in the context of a particular zone. Can take any value taken as the first argument to setZone() - * @param {string} [opts.locale='system\'s locale'] - a locale to set on the resulting DateTime instance - * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance - * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance - * @example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25' - * @example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01' - * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06 - * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }), - * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' }) - * @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' }) - * @example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13' - * @example DateTime.fromObject({ localWeekYear: 2022, localWeekNumber: 1, localWeekday: 1 }, { locale: "en-US" }).toISODate() //=> '2021-12-26' - * @return {DateTime} - */ - static fromObject(obj, opts = {}) { - obj = obj || {} - const zoneToUse = normalizeZone(opts.zone, Settings.defaultZone) - if (!zoneToUse.isValid) { - return DateTime.invalid(unsupportedZone(zoneToUse)) - } - - const loc = Locale.fromObject(opts) - const normalized = normalizeObject(obj, normalizeUnitWithLocalWeeks) - const { minDaysInFirstWeek, startOfWeek } = usesLocalWeekValues( - normalized, - loc - ) - - const tsNow = Settings.now(), - offsetProvis = !isUndefined(opts.specificOffset) - ? opts.specificOffset - : zoneToUse.offset(tsNow), - containsOrdinal = !isUndefined(normalized.ordinal), - containsGregorYear = !isUndefined(normalized.year), - containsGregorMD = - !isUndefined(normalized.month) || !isUndefined(normalized.day), - containsGregor = containsGregorYear || containsGregorMD, - definiteWeekDef = normalized.weekYear || normalized.weekNumber - - // cases: - // just a weekday -> this week's instance of that weekday, no worries - // (gregorian data or ordinal) + (weekYear or weekNumber) -> error - // (gregorian month or day) + ordinal -> error - // otherwise just use weeks or ordinals or gregorian, depending on what's specified - - if ((containsGregor || containsOrdinal) && definiteWeekDef) { - throw new ConflictingSpecificationError( - "Can't mix weekYear/weekNumber units with year/month/day or ordinals" - ) - } - - if (containsGregorMD && containsOrdinal) { - throw new ConflictingSpecificationError( - "Can't mix ordinal dates with month/day" - ) - } - - const useWeekData = - definiteWeekDef || (normalized.weekday && !containsGregor) - - // configure ourselves to deal with gregorian dates or week stuff - let units, - defaultValues, - objNow = tsToObj(tsNow, offsetProvis) - if (useWeekData) { - units = orderedWeekUnits - defaultValues = defaultWeekUnitValues - objNow = gregorianToWeek(objNow, minDaysInFirstWeek, startOfWeek) - } else if (containsOrdinal) { - units = orderedOrdinalUnits - defaultValues = defaultOrdinalUnitValues - objNow = gregorianToOrdinal(objNow) - } else { - units = orderedUnits - defaultValues = defaultUnitValues - } - - // set default values for missing stuff - let foundFirst = false - for (const u of units) { - const v = normalized[u] - if (!isUndefined(v)) { - foundFirst = true - } else if (foundFirst) { - normalized[u] = defaultValues[u] - } else { - normalized[u] = objNow[u] - } - } - - // make sure the values we have are in range - const higherOrderInvalid = useWeekData - ? hasInvalidWeekData(normalized, minDaysInFirstWeek, startOfWeek) - : containsOrdinal - ? hasInvalidOrdinalData(normalized) - : hasInvalidGregorianData(normalized), - invalid = higherOrderInvalid || hasInvalidTimeData(normalized) - - if (invalid) { - return DateTime.invalid(invalid) - } - - // compute the actual time - const gregorian = useWeekData - ? weekToGregorian(normalized, minDaysInFirstWeek, startOfWeek) - : containsOrdinal - ? ordinalToGregorian(normalized) - : normalized, - [tsFinal, offsetFinal] = objToTS(gregorian, offsetProvis, zoneToUse), - inst = new DateTime({ - ts: tsFinal, - zone: zoneToUse, - o: offsetFinal, - loc, - }) - - // gregorian data + weekday serves only to validate - if (normalized.weekday && containsGregor && obj.weekday !== inst.weekday) { - return DateTime.invalid( - 'mismatched weekday', - `you can't specify both a weekday of ${ - normalized.weekday - } and a date of ${inst.toISO()}` - ) - } - - return inst - } - - /** - * Create a DateTime from an ISO 8601 string - * @param {string} text - the ISO string - * @param {Object} opts - options to affect the creation - * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the time to this zone - * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one - * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance - * @param {string} [opts.outputCalendar] - the output calendar to set on the resulting DateTime instance - * @param {string} [opts.numberingSystem] - the numbering system to set on the resulting DateTime instance - * @example DateTime.fromISO('2016-05-25T09:08:34.123') - * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00') - * @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00', {setZone: true}) - * @example DateTime.fromISO('2016-05-25T09:08:34.123', {zone: 'utc'}) - * @example DateTime.fromISO('2016-W05-4') - * @return {DateTime} - */ - static fromISO(text, opts = {}) { - const [vals, parsedZone] = parseISODate(text) - return parseDataToDateTime(vals, parsedZone, opts, 'ISO 8601', text) - } - - /** - * Create a DateTime from an RFC 2822 string - * @param {string} text - the RFC 2822 string - * @param {Object} opts - options to affect the creation - * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since the offset is always specified in the string itself, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in. - * @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one - * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance - * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance - * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance - * @example DateTime.fromRFC2822('25 Nov 2016 13:23:12 GMT') - * @example DateTime.fromRFC2822('Fri, 25 Nov 2016 13:23:12 +0600') - * @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z') - * @return {DateTime} - */ - static fromRFC2822(text, opts = {}) { - const [vals, parsedZone] = parseRFC2822Date(text) - return parseDataToDateTime(vals, parsedZone, opts, 'RFC 2822', text) - } - - /** - * Create a DateTime from an HTTP header date - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 - * @param {string} text - the HTTP header date - * @param {Object} opts - options to affect the creation - * @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since HTTP dates are always in UTC, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in. - * @param {boolean} [opts.setZone=false] - override the zone with the fixed-offset zone specified in the string. For HTTP dates, this is always UTC, so this option is equivalent to setting the `zone` option to 'utc', but this option is included for consistency with similar methods. - * @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance - * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance - * @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance - * @example DateTime.fromHTTP('Sun, 06 Nov 1994 08:49:37 GMT') - * @example DateTime.fromHTTP('Sunday, 06-Nov-94 08:49:37 GMT') - * @example DateTime.fromHTTP('Sun Nov 6 08:49:37 1994') - * @return {DateTime} - */ - static fromHTTP(text, opts = {}) { - const [vals, parsedZone] = parseHTTPDate(text) - return parseDataToDateTime(vals, parsedZone, opts, 'HTTP', opts) - } - - /** - * Create a DateTime from an input string and format string. - * Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/parsing?id=table-of-tokens). - * @param {string} text - the string to parse - * @param {string} fmt - the format the string is expected to be in (see the link below for the formats) - * @param {Object} opts - options to affect the creation - * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone - * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one - * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale - * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system - * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance - * @return {DateTime} - */ - static fromFormat(text, fmt, opts = {}) { - if (isUndefined(text) || isUndefined(fmt)) { - throw new InvalidArgumentError( - 'fromFormat requires an input string and a format' - ) - } - - const { locale = null, numberingSystem = null } = opts, - localeToUse = Locale.fromOpts({ - locale, - numberingSystem, - defaultToEN: true, - }), - [vals, parsedZone, specificOffset, invalid] = parseFromTokens( - localeToUse, - text, - fmt - ) - if (invalid) { - return DateTime.invalid(invalid) - } else { - return parseDataToDateTime( - vals, - parsedZone, - opts, - `format ${fmt}`, - text, - specificOffset - ) - } - } - - /** - * @deprecated use fromFormat instead - */ - static fromString(text, fmt, opts = {}) { - return DateTime.fromFormat(text, fmt, opts) - } - - /** - * Create a DateTime from a SQL date, time, or datetime - * Defaults to en-US if no locale has been specified, regardless of the system's locale - * @param {string} text - the string to parse - * @param {Object} opts - options to affect the creation - * @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone - * @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one - * @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale - * @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system - * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance - * @example DateTime.fromSQL('2017-05-15') - * @example DateTime.fromSQL('2017-05-15 09:12:34') - * @example DateTime.fromSQL('2017-05-15 09:12:34.342') - * @example DateTime.fromSQL('2017-05-15 09:12:34.342+06:00') - * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles') - * @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles', { setZone: true }) - * @example DateTime.fromSQL('2017-05-15 09:12:34.342', { zone: 'America/Los_Angeles' }) - * @example DateTime.fromSQL('09:12:34.342') - * @return {DateTime} - */ - static fromSQL(text, opts = {}) { - const [vals, parsedZone] = parseSQL(text) - return parseDataToDateTime(vals, parsedZone, opts, 'SQL', text) - } - - /** - * Create an invalid DateTime. - * @param {string} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent. - * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information - * @return {DateTime} - */ - static invalid(reason, explanation = null) { - if (!reason) { - throw new InvalidArgumentError( - 'need to specify a reason the DateTime is invalid' - ) - } - - const invalid = - reason instanceof Invalid ? reason : new Invalid(reason, explanation) - - if (Settings.throwOnInvalid) { - throw new InvalidDateTimeError(invalid) - } else { - return new DateTime({ invalid }) - } - } - - /** - * Check if an object is an instance of DateTime. Works across context boundaries - * @param {object} o - * @return {boolean} - */ - static isDateTime(o) { - return (o && o.isLuxonDateTime) || false - } - - /** - * Produce the format string for a set of options - * @param formatOpts - * @param localeOpts - * @returns {string} - */ - static parseFormatForOpts(formatOpts, localeOpts = {}) { - const tokenList = formatOptsToTokens( - formatOpts, - Locale.fromObject(localeOpts) - ) - return !tokenList ? null : tokenList.map((t) => (t ? t.val : null)).join('') - } - - /** - * Produce the the fully expanded format token for the locale - * Does NOT quote characters, so quoted tokens will not round trip correctly - * @param fmt - * @param localeOpts - * @returns {string} - */ - static expandFormat(fmt, localeOpts = {}) { - const expanded = expandMacroTokens( - Formatter.parseFormat(fmt), - Locale.fromObject(localeOpts) - ) - return expanded.map((t) => t.val).join('') - } - - // INFO - - /** - * Get the value of unit. - * @param {string} unit - a unit such as 'minute' or 'day' - * @example DateTime.local(2017, 7, 4).get('month'); //=> 7 - * @example DateTime.local(2017, 7, 4).get('day'); //=> 4 - * @return {number} - */ - get(unit) { - return this[unit] - } - - /** - * Returns whether the DateTime is valid. Invalid DateTimes occur when: - * * The DateTime was created from invalid calendar information, such as the 13th month or February 30 - * * The DateTime was created by an operation on another invalid date - * @type {boolean} - */ - get isValid() { - return this.invalid === null - } - - /** - * Returns an error code if this DateTime is invalid, or null if the DateTime is valid - * @type {string} - */ - get invalidReason() { - return this.invalid ? this.invalid.reason : null - } - - /** - * Returns an explanation of why this DateTime became invalid, or null if the DateTime is valid - * @type {string} - */ - get invalidExplanation() { - return this.invalid ? this.invalid.explanation : null - } - - /** - * Get the locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime - * - * @type {string} - */ - get locale() { - return this.isValid ? this.loc.locale : null - } - - /** - * Get the numbering system of a DateTime, such 'beng'. The numbering system is used when formatting the DateTime - * - * @type {string} - */ - get numberingSystem() { - return this.isValid ? this.loc.numberingSystem : null - } - - /** - * Get the output calendar of a DateTime, such 'islamic'. The output calendar is used when formatting the DateTime - * - * @type {string} - */ - get outputCalendar() { - return this.isValid ? this.loc.outputCalendar : null - } - - /** - * Get the time zone associated with this DateTime. - * @type {Zone} - */ - get zone() { - return this._zone - } - - /** - * Get the name of the time zone. - * @type {string} - */ - get zoneName() { - return this.isValid ? this.zone.name : null - } - - /** - * Get the year - * @example DateTime.local(2017, 5, 25).year //=> 2017 - * @type {number} - */ - get year() { - return this.isValid ? this.c.year : NaN - } - - /** - * Get the quarter - * @example DateTime.local(2017, 5, 25).quarter //=> 2 - * @type {number} - */ - get quarter() { - return this.isValid ? Math.ceil(this.c.month / 3) : NaN - } - - /** - * Get the month (1-12). - * @example DateTime.local(2017, 5, 25).month //=> 5 - * @type {number} - */ - get month() { - return this.isValid ? this.c.month : NaN - } - - /** - * Get the day of the month (1-30ish). - * @example DateTime.local(2017, 5, 25).day //=> 25 - * @type {number} - */ - get day() { - return this.isValid ? this.c.day : NaN - } - - /** - * Get the hour of the day (0-23). - * @example DateTime.local(2017, 5, 25, 9).hour //=> 9 - * @type {number} - */ - get hour() { - return this.isValid ? this.c.hour : NaN - } - - /** - * Get the minute of the hour (0-59). - * @example DateTime.local(2017, 5, 25, 9, 30).minute //=> 30 - * @type {number} - */ - get minute() { - return this.isValid ? this.c.minute : NaN - } - - /** - * Get the second of the minute (0-59). - * @example DateTime.local(2017, 5, 25, 9, 30, 52).second //=> 52 - * @type {number} - */ - get second() { - return this.isValid ? this.c.second : NaN - } - - /** - * Get the millisecond of the second (0-999). - * @example DateTime.local(2017, 5, 25, 9, 30, 52, 654).millisecond //=> 654 - * @type {number} - */ - get millisecond() { - return this.isValid ? this.c.millisecond : NaN - } - - /** - * Get the week year - * @see https://en.wikipedia.org/wiki/ISO_week_date - * @example DateTime.local(2014, 12, 31).weekYear //=> 2015 - * @type {number} - */ - get weekYear() { - return this.isValid ? possiblyCachedWeekData(this).weekYear : NaN - } - - /** - * Get the week number of the week year (1-52ish). - * @see https://en.wikipedia.org/wiki/ISO_week_date - * @example DateTime.local(2017, 5, 25).weekNumber //=> 21 - * @type {number} - */ - get weekNumber() { - return this.isValid ? possiblyCachedWeekData(this).weekNumber : NaN - } - - /** - * Get the day of the week. - * 1 is Monday and 7 is Sunday - * @see https://en.wikipedia.org/wiki/ISO_week_date - * @example DateTime.local(2014, 11, 31).weekday //=> 4 - * @type {number} - */ - get weekday() { - return this.isValid ? possiblyCachedWeekData(this).weekday : NaN - } - - /** - * Returns true if this date is on a weekend according to the locale, false otherwise - * @returns {boolean} - */ - get isWeekend() { - return this.isValid && this.loc.getWeekendDays().includes(this.weekday) - } - - /** - * Get the day of the week according to the locale. - * 1 is the first day of the week and 7 is the last day of the week. - * If the locale assigns Sunday as the first day of the week, then a date which is a Sunday will return 1, - * @returns {number} - */ - get localWeekday() { - return this.isValid ? possiblyCachedLocalWeekData(this).weekday : NaN - } - - /** - * Get the week number of the week year according to the locale. Different locales assign week numbers differently, - * because the week can start on different days of the week (see localWeekday) and because a different number of days - * is required for a week to count as the first week of a year. - * @returns {number} - */ - get localWeekNumber() { - return this.isValid ? possiblyCachedLocalWeekData(this).weekNumber : NaN - } - - /** - * Get the week year according to the locale. Different locales assign week numbers (and therefor week years) - * differently, see localWeekNumber. - * @returns {number} - */ - get localWeekYear() { - return this.isValid ? possiblyCachedLocalWeekData(this).weekYear : NaN - } - - /** - * Get the ordinal (meaning the day of the year) - * @example DateTime.local(2017, 5, 25).ordinal //=> 145 - * @type {number|DateTime} - */ - get ordinal() { - return this.isValid ? gregorianToOrdinal(this.c).ordinal : NaN - } - - /** - * Get the human readable short month name, such as 'Oct'. - * Defaults to the system's locale if no locale has been specified - * @example DateTime.local(2017, 10, 30).monthShort //=> Oct - * @type {string} - */ - get monthShort() { - return this.isValid - ? Info.months('short', { locObj: this.loc })[this.month - 1] - : null - } - - /** - * Get the human readable long month name, such as 'October'. - * Defaults to the system's locale if no locale has been specified - * @example DateTime.local(2017, 10, 30).monthLong //=> October - * @type {string} - */ - get monthLong() { - return this.isValid - ? Info.months('long', { locObj: this.loc })[this.month - 1] - : null - } - - /** - * Get the human readable short weekday, such as 'Mon'. - * Defaults to the system's locale if no locale has been specified - * @example DateTime.local(2017, 10, 30).weekdayShort //=> Mon - * @type {string} - */ - get weekdayShort() { - return this.isValid - ? Info.weekdays('short', { locObj: this.loc })[this.weekday - 1] - : null - } - - /** - * Get the human readable long weekday, such as 'Monday'. - * Defaults to the system's locale if no locale has been specified - * @example DateTime.local(2017, 10, 30).weekdayLong //=> Monday - * @type {string} - */ - get weekdayLong() { - return this.isValid - ? Info.weekdays('long', { locObj: this.loc })[this.weekday - 1] - : null - } - - /** - * Get the UTC offset of this DateTime in minutes - * @example DateTime.now().offset //=> -240 - * @example DateTime.utc().offset //=> 0 - * @type {number} - */ - get offset() { - return this.isValid ? +this.o : NaN - } - - /** - * Get the short human name for the zone's current offset, for example "EST" or "EDT". - * Defaults to the system's locale if no locale has been specified - * @type {string} - */ - get offsetNameShort() { - if (this.isValid) { - return this.zone.offsetName(this.ts, { - format: 'short', - locale: this.locale, - }) - } else { - return null - } - } - - /** - * Get the long human name for the zone's current offset, for example "Eastern Standard Time" or "Eastern Daylight Time". - * Defaults to the system's locale if no locale has been specified - * @type {string} - */ - get offsetNameLong() { - if (this.isValid) { - return this.zone.offsetName(this.ts, { - format: 'long', - locale: this.locale, - }) - } else { - return null - } - } - - /** - * Get whether this zone's offset ever changes, as in a DST. - * @type {boolean} - */ - get isOffsetFixed() { - return this.isValid ? this.zone.isUniversal : null - } - - /** - * Get whether the DateTime is in a DST. - * @type {boolean} - */ - get isInDST() { - if (this.isOffsetFixed) { - return false - } else { - return ( - this.offset > this.set({ month: 1, day: 1 }).offset || - this.offset > this.set({ month: 5 }).offset - ) - } - } - - /** - * Get those DateTimes which have the same local time as this DateTime, but a different offset from UTC - * in this DateTime's zone. During DST changes local time can be ambiguous, for example - * `2023-10-29T02:30:00` in `Europe/Berlin` can have offset `+01:00` or `+02:00`. - * This method will return both possible DateTimes if this DateTime's local time is ambiguous. - * @returns {DateTime[]} - */ - getPossibleOffsets() { - if (!this.isValid || this.isOffsetFixed) { - return [this] - } - const dayMs = 86400000 - const minuteMs = 60000 - const localTS = objToLocalTS(this.c) - const oEarlier = this.zone.offset(localTS - dayMs) - const oLater = this.zone.offset(localTS + dayMs) - - const o1 = this.zone.offset(localTS - oEarlier * minuteMs) - const o2 = this.zone.offset(localTS - oLater * minuteMs) - if (o1 === o2) { - return [this] - } - const ts1 = localTS - o1 * minuteMs - const ts2 = localTS - o2 * minuteMs - const c1 = tsToObj(ts1, o1) - const c2 = tsToObj(ts2, o2) - if ( - c1.hour === c2.hour && - c1.minute === c2.minute && - c1.second === c2.second && - c1.millisecond === c2.millisecond - ) { - return [clone(this, { ts: ts1 }), clone(this, { ts: ts2 })] - } - return [this] - } - - /** - * Returns true if this DateTime is in a leap year, false otherwise - * @example DateTime.local(2016).isInLeapYear //=> true - * @example DateTime.local(2013).isInLeapYear //=> false - * @type {boolean} - */ - get isInLeapYear() { - return isLeapYear(this.year) - } - - /** - * Returns the number of days in this DateTime's month - * @example DateTime.local(2016, 2).daysInMonth //=> 29 - * @example DateTime.local(2016, 3).daysInMonth //=> 31 - * @type {number} - */ - get daysInMonth() { - return daysInMonth(this.year, this.month) - } - - /** - * Returns the number of days in this DateTime's year - * @example DateTime.local(2016).daysInYear //=> 366 - * @example DateTime.local(2013).daysInYear //=> 365 - * @type {number} - */ - get daysInYear() { - return this.isValid ? daysInYear(this.year) : NaN - } - - /** - * Returns the number of weeks in this DateTime's year - * @see https://en.wikipedia.org/wiki/ISO_week_date - * @example DateTime.local(2004).weeksInWeekYear //=> 53 - * @example DateTime.local(2013).weeksInWeekYear //=> 52 - * @type {number} - */ - get weeksInWeekYear() { - return this.isValid ? weeksInWeekYear(this.weekYear) : NaN - } - - /** - * Returns the number of weeks in this DateTime's local week year - * @example DateTime.local(2020, 6, {locale: 'en-US'}).weeksInLocalWeekYear //=> 52 - * @example DateTime.local(2020, 6, {locale: 'de-DE'}).weeksInLocalWeekYear //=> 53 - * @type {number} - */ - get weeksInLocalWeekYear() { - return this.isValid - ? weeksInWeekYear( - this.localWeekYear, - this.loc.getMinDaysInFirstWeek(), - this.loc.getStartOfWeek() - ) - : NaN - } - - /** - * Returns the resolved Intl options for this DateTime. - * This is useful in understanding the behavior of formatting methods - * @param {Object} opts - the same options as toLocaleString - * @return {Object} - */ - resolvedLocaleOptions(opts = {}) { - const { locale, numberingSystem, calendar } = Formatter.create( - this.loc.clone(opts), - opts - ).resolvedOptions(this) - return { locale, numberingSystem, outputCalendar: calendar } - } - - // TRANSFORM - - /** - * "Set" the DateTime's zone to UTC. Returns a newly-constructed DateTime. - * - * Equivalent to {@link DateTime#setZone}('utc') - * @param {number} [offset=0] - optionally, an offset from UTC in minutes - * @param {Object} [opts={}] - options to pass to `setZone()` - * @return {DateTime} - */ - toUTC(offset = 0, opts = {}) { - return this.setZone(FixedOffsetZone.instance(offset), opts) - } - - /** - * "Set" the DateTime's zone to the host's local zone. Returns a newly-constructed DateTime. - * - * Equivalent to `setZone('local')` - * @return {DateTime} - */ - toLocal() { - return this.setZone(Settings.defaultZone) - } - - /** - * "Set" the DateTime's zone to specified zone. Returns a newly-constructed DateTime. - * - * By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link DateTime#plus}. You may wish to use {@link DateTime#toLocal} and {@link DateTime#toUTC} which provide simple convenience wrappers for commonly used zones. - * @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link DateTime#Zone} class. - * @param {Object} opts - options - * @param {boolean} [opts.keepLocalTime=false] - If true, adjust the underlying time so that the local time stays the same, but in the target zone. You should rarely need this. - * @return {DateTime} - */ - setZone(zone, { keepLocalTime = false, keepCalendarTime = false } = {}) { - zone = normalizeZone(zone, Settings.defaultZone) - if (zone.equals(this.zone)) { - return this - } else if (!zone.isValid) { - return DateTime.invalid(unsupportedZone(zone)) - } else { - let newTS = this.ts - if (keepLocalTime || keepCalendarTime) { - const offsetGuess = zone.offset(this.ts) - const asObj = this.toObject() - ;[newTS] = objToTS(asObj, offsetGuess, zone) - } - return clone(this, { ts: newTS, zone }) - } - } - - /** - * "Set" the locale, numberingSystem, or outputCalendar. Returns a newly-constructed DateTime. - * @param {Object} properties - the properties to set - * @example DateTime.local(2017, 5, 25).reconfigure({ locale: 'en-GB' }) - * @return {DateTime} - */ - reconfigure({ locale, numberingSystem, outputCalendar } = {}) { - const loc = this.loc.clone({ locale, numberingSystem, outputCalendar }) - return clone(this, { loc }) - } - - /** - * "Set" the locale. Returns a newly-constructed DateTime. - * Just a convenient alias for reconfigure({ locale }) - * @example DateTime.local(2017, 5, 25).setLocale('en-GB') - * @return {DateTime} - */ - setLocale(locale) { - return this.reconfigure({ locale }) - } - - /** - * "Set" the values of specified units. Returns a newly-constructed DateTime. - * You can only set units with this method; for "setting" metadata, see {@link DateTime#reconfigure} and {@link DateTime#setZone}. - * - * This method also supports setting locale-based week units, i.e. `localWeekday`, `localWeekNumber` and `localWeekYear`. - * They cannot be mixed with ISO-week units like `weekday`. - * @param {Object} values - a mapping of units to numbers - * @example dt.set({ year: 2017 }) - * @example dt.set({ hour: 8, minute: 30 }) - * @example dt.set({ weekday: 5 }) - * @example dt.set({ year: 2005, ordinal: 234 }) - * @return {DateTime} - */ - set(values) { - if (!this.isValid) return this - - const normalized = normalizeObject(values, normalizeUnitWithLocalWeeks) - const { minDaysInFirstWeek, startOfWeek } = usesLocalWeekValues( - normalized, - this.loc - ) - - const settingWeekStuff = - !isUndefined(normalized.weekYear) || - !isUndefined(normalized.weekNumber) || - !isUndefined(normalized.weekday), - containsOrdinal = !isUndefined(normalized.ordinal), - containsGregorYear = !isUndefined(normalized.year), - containsGregorMD = - !isUndefined(normalized.month) || !isUndefined(normalized.day), - containsGregor = containsGregorYear || containsGregorMD, - definiteWeekDef = normalized.weekYear || normalized.weekNumber - - if ((containsGregor || containsOrdinal) && definiteWeekDef) { - throw new ConflictingSpecificationError( - "Can't mix weekYear/weekNumber units with year/month/day or ordinals" - ) - } - - if (containsGregorMD && containsOrdinal) { - throw new ConflictingSpecificationError( - "Can't mix ordinal dates with month/day" - ) - } - - let mixed - if (settingWeekStuff) { - mixed = weekToGregorian( - { - ...gregorianToWeek(this.c, minDaysInFirstWeek, startOfWeek), - ...normalized, - }, - minDaysInFirstWeek, - startOfWeek - ) - } else if (!isUndefined(normalized.ordinal)) { - mixed = ordinalToGregorian({ - ...gregorianToOrdinal(this.c), - ...normalized, - }) - } else { - mixed = { ...this.toObject(), ...normalized } - - // if we didn't set the day but we ended up on an overflow date, - // use the last day of the right month - if (isUndefined(normalized.day)) { - mixed.day = Math.min(daysInMonth(mixed.year, mixed.month), mixed.day) - } - } - - const [ts, o] = objToTS(mixed, this.o, this.zone) - return clone(this, { ts, o }) - } - - /** - * Add a period of time to this DateTime and return the resulting DateTime - * - * Adding hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds. Adding days, months, or years shifts the calendar, accounting for DSTs and leap years along the way. Thus, `dt.plus({ hours: 24 })` may result in a different time than `dt.plus({ days: 1 })` if there's a DST shift in between. - * @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() - * @example DateTime.now().plus(123) //~> in 123 milliseconds - * @example DateTime.now().plus({ minutes: 15 }) //~> in 15 minutes - * @example DateTime.now().plus({ days: 1 }) //~> this time tomorrow - * @example DateTime.now().plus({ days: -1 }) //~> this time yesterday - * @example DateTime.now().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min - * @example DateTime.now().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min - * @return {DateTime} - */ - plus(duration) { - if (!this.isValid) return this - const dur = Duration.fromDurationLike(duration) - return clone(this, adjustTime(this, dur)) - } - - /** - * Subtract a period of time to this DateTime and return the resulting DateTime - * See {@link DateTime#plus} - * @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject() - @return {DateTime} - */ - minus(duration) { - if (!this.isValid) return this - const dur = Duration.fromDurationLike(duration).negate() - return clone(this, adjustTime(this, dur)) - } - - /** - * "Set" this DateTime to the beginning of a unit of time. - * @param {string} unit - The unit to go to the beginning of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'. - * @param {Object} opts - options - * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week - * @example DateTime.local(2014, 3, 3).startOf('month').toISODate(); //=> '2014-03-01' - * @example DateTime.local(2014, 3, 3).startOf('year').toISODate(); //=> '2014-01-01' - * @example DateTime.local(2014, 3, 3).startOf('week').toISODate(); //=> '2014-03-03', weeks always start on Mondays - * @example DateTime.local(2014, 3, 3, 5, 30).startOf('day').toISOTime(); //=> '00:00.000-05:00' - * @example DateTime.local(2014, 3, 3, 5, 30).startOf('hour').toISOTime(); //=> '05:00:00.000-05:00' - * @return {DateTime} - */ - startOf(unit, { useLocaleWeeks = false } = {}) { - if (!this.isValid) return this - - const o = {}, - normalizedUnit = Duration.normalizeUnit(unit) - switch (normalizedUnit) { - case 'years': - o.month = 1 - // falls through - case 'quarters': - case 'months': - o.day = 1 - // falls through - case 'weeks': - case 'days': - o.hour = 0 - // falls through - case 'hours': - o.minute = 0 - // falls through - case 'minutes': - o.second = 0 - // falls through - case 'seconds': - o.millisecond = 0 - break - // no default, invalid units throw in normalizeUnit() - } - - if (normalizedUnit === 'weeks') { - if (useLocaleWeeks) { - const startOfWeek = this.loc.getStartOfWeek() - const { weekday } = this - if (weekday < startOfWeek) { - o.weekNumber = this.weekNumber - 1 - } - o.weekday = startOfWeek - } else { - o.weekday = 1 - } - } - - if (normalizedUnit === 'quarters') { - const q = Math.ceil(this.month / 3) - o.month = (q - 1) * 3 + 1 - } - - return this.set(o) - } - - /** - * "Set" this DateTime to the end (meaning the last millisecond) of a unit of time - * @param {string} unit - The unit to go to the end of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'. - * @param {Object} opts - options - * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week - * @example DateTime.local(2014, 3, 3).endOf('month').toISO(); //=> '2014-03-31T23:59:59.999-05:00' - * @example DateTime.local(2014, 3, 3).endOf('year').toISO(); //=> '2014-12-31T23:59:59.999-05:00' - * @example DateTime.local(2014, 3, 3).endOf('week').toISO(); // => '2014-03-09T23:59:59.999-05:00', weeks start on Mondays - * @example DateTime.local(2014, 3, 3, 5, 30).endOf('day').toISO(); //=> '2014-03-03T23:59:59.999-05:00' - * @example DateTime.local(2014, 3, 3, 5, 30).endOf('hour').toISO(); //=> '2014-03-03T05:59:59.999-05:00' - * @return {DateTime} - */ - endOf(unit, opts) { - return this.isValid - ? this.plus({ [unit]: 1 }) - .startOf(unit, opts) - .minus(1) - : this - } - - // OUTPUT - - /** - * Returns a string representation of this DateTime formatted according to the specified format string. - * **You may not want this.** See {@link DateTime#toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/formatting?id=table-of-tokens). - * Defaults to en-US if no locale has been specified, regardless of the system's locale. - * @param {string} fmt - the format string - * @param {Object} opts - opts to override the configuration options on this DateTime - * @example DateTime.now().toFormat('yyyy LLL dd') //=> '2017 Apr 22' - * @example DateTime.now().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22' - * @example DateTime.now().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22' - * @example DateTime.now().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes' - * @return {string} - */ - toFormat(fmt, opts = {}) { - return this.isValid - ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString( - this, - fmt - ) - : INVALID - } - - /** - * Returns a localized string representing this date. Accepts the same options as the Intl.DateTimeFormat constructor and any presets defined by Luxon, such as `DateTime.DATE_FULL` or `DateTime.TIME_SIMPLE`. - * The exact behavior of this method is browser-specific, but in general it will return an appropriate representation - * of the DateTime in the assigned locale. - * Defaults to the system's locale if no locale has been specified - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat - * @param formatOpts {Object} - Intl.DateTimeFormat constructor options and configuration options - * @param {Object} opts - opts to override the configuration options on this DateTime - * @example DateTime.now().toLocaleString(); //=> 4/20/2017 - * @example DateTime.now().setLocale('en-gb').toLocaleString(); //=> '20/04/2017' - * @example DateTime.now().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017' - * @example DateTime.now().toLocaleString(DateTime.DATE_FULL, { locale: 'fr' }); //=> '28 août 2022' - * @example DateTime.now().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM' - * @example DateTime.now().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM' - * @example DateTime.now().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20' - * @example DateTime.now().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM' - * @example DateTime.now().toLocaleString({ hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }); //=> '11:32' - * @return {string} - */ - toLocaleString(formatOpts = DATE_SHORT, opts = {}) { - return this.isValid - ? Formatter.create(this.loc.clone(opts), formatOpts).formatDateTime(this) - : INVALID - } - - /** - * Returns an array of format "parts", meaning individual tokens along with metadata. This is allows callers to post-process individual sections of the formatted output. - * Defaults to the system's locale if no locale has been specified - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts - * @param opts {Object} - Intl.DateTimeFormat constructor options, same as `toLocaleString`. - * @example DateTime.now().toLocaleParts(); //=> [ - * //=> { type: 'day', value: '25' }, - * //=> { type: 'literal', value: '/' }, - * //=> { type: 'month', value: '05' }, - * //=> { type: 'literal', value: '/' }, - * //=> { type: 'year', value: '1982' } - * //=> ] - */ - toLocaleParts(opts = {}) { - return this.isValid - ? Formatter.create(this.loc.clone(opts), opts).formatDateTimeParts(this) - : [] - } - - /** - * Returns an ISO 8601-compliant string representation of this DateTime - * @param {Object} opts - options - * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 - * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 - * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' - * @param {boolean} [opts.extendedZone=false] - add the time zone format extension - * @param {string} [opts.format='extended'] - choose between the basic and extended format - * @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z' - * @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00' - * @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335' - * @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400' - * @return {string} - */ - toISO({ - format = 'extended', - suppressSeconds = false, - suppressMilliseconds = false, - includeOffset = true, - extendedZone = false, - } = {}) { - if (!this.isValid) { - return null - } - - const ext = format === 'extended' - - let c = toISODate(this, ext) - c += 'T' - c += toISOTime( - this, - ext, - suppressSeconds, - suppressMilliseconds, - includeOffset, - extendedZone - ) - return c - } - - /** - * Returns an ISO 8601-compliant string representation of this DateTime's date component - * @param {Object} opts - options - * @param {string} [opts.format='extended'] - choose between the basic and extended format - * @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25' - * @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525' - * @return {string} - */ - toISODate({ format = 'extended' } = {}) { - if (!this.isValid) { - return null - } - - return toISODate(this, format === 'extended') - } - - /** - * Returns an ISO 8601-compliant string representation of this DateTime's week date - * @example DateTime.utc(1982, 5, 25).toISOWeekDate() //=> '1982-W21-2' - * @return {string} - */ - toISOWeekDate() { - return toTechFormat(this, "kkkk-'W'WW-c") - } - - /** - * Returns an ISO 8601-compliant string representation of this DateTime's time component - * @param {Object} opts - options - * @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0 - * @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0 - * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' - * @param {boolean} [opts.extendedZone=true] - add the time zone format extension - * @param {boolean} [opts.includePrefix=false] - include the `T` prefix - * @param {string} [opts.format='extended'] - choose between the basic and extended format - * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z' - * @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z' - * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z' - * @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z' - * @return {string} - */ - toISOTime({ - suppressMilliseconds = false, - suppressSeconds = false, - includeOffset = true, - includePrefix = false, - extendedZone = false, - format = 'extended', - } = {}) { - if (!this.isValid) { - return null - } - - let c = includePrefix ? 'T' : '' - return ( - c + - toISOTime( - this, - format === 'extended', - suppressSeconds, - suppressMilliseconds, - includeOffset, - extendedZone - ) - ) - } - - /** - * Returns an RFC 2822-compatible string representation of this DateTime - * @example DateTime.utc(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 +0000' - * @example DateTime.local(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 -0400' - * @return {string} - */ - toRFC2822() { - return toTechFormat(this, 'EEE, dd LLL yyyy HH:mm:ss ZZZ', false) - } - - /** - * Returns a string representation of this DateTime appropriate for use in HTTP headers. The output is always expressed in GMT. - * Specifically, the string conforms to RFC 1123. - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 - * @example DateTime.utc(2014, 7, 13).toHTTP() //=> 'Sun, 13 Jul 2014 00:00:00 GMT' - * @example DateTime.utc(2014, 7, 13, 19).toHTTP() //=> 'Sun, 13 Jul 2014 19:00:00 GMT' - * @return {string} - */ - toHTTP() { - return toTechFormat(this.toUTC(), "EEE, dd LLL yyyy HH:mm:ss 'GMT'") - } - - /** - * Returns a string representation of this DateTime appropriate for use in SQL Date - * @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13' - * @return {string} - */ - toSQLDate() { - if (!this.isValid) { - return null - } - return toISODate(this, true) - } - - /** - * Returns a string representation of this DateTime appropriate for use in SQL Time - * @param {Object} opts - options - * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset. - * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' - * @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00' - * @example DateTime.utc().toSQL() //=> '05:15:16.345' - * @example DateTime.now().toSQL() //=> '05:15:16.345 -04:00' - * @example DateTime.now().toSQL({ includeOffset: false }) //=> '05:15:16.345' - * @example DateTime.now().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York' - * @return {string} - */ - toSQLTime({ - includeOffset = true, - includeZone = false, - includeOffsetSpace = true, - } = {}) { - let fmt = 'HH:mm:ss.SSS' - - if (includeZone || includeOffset) { - if (includeOffsetSpace) { - fmt += ' ' - } - if (includeZone) { - fmt += 'z' - } else if (includeOffset) { - fmt += 'ZZ' - } - } - - return toTechFormat(this, fmt, true) - } - - /** - * Returns a string representation of this DateTime appropriate for use in SQL DateTime - * @param {Object} opts - options - * @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset. - * @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00' - * @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00' - * @example DateTime.utc(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 Z' - * @example DateTime.local(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 -04:00' - * @example DateTime.local(2014, 7, 13).toSQL({ includeOffset: false }) //=> '2014-07-13 00:00:00.000' - * @example DateTime.local(2014, 7, 13).toSQL({ includeZone: true }) //=> '2014-07-13 00:00:00.000 America/New_York' - * @return {string} - */ - toSQL(opts = {}) { - if (!this.isValid) { - return null - } - - return `${this.toSQLDate()} ${this.toSQLTime(opts)}` - } - - /** - * Returns a string representation of this DateTime appropriate for debugging - * @return {string} - */ - toString() { - return this.isValid ? this.toISO() : INVALID - } - - /** - * Returns a string representation of this DateTime appropriate for the REPL. - * @return {string} - */ - [Symbol.for('nodejs.util.inspect.custom')]() { - if (this.isValid) { - return `DateTime { ts: ${this.toISO()}, zone: ${ - this.zone.name - }, locale: ${this.locale} }` - } else { - return `DateTime { Invalid, reason: ${this.invalidReason} }` - } - } - - /** - * Returns the epoch milliseconds of this DateTime. Alias of {@link DateTime#toMillis} - * @return {number} - */ - valueOf() { - return this.toMillis() - } - - /** - * Returns the epoch milliseconds of this DateTime. - * @return {number} - */ - toMillis() { - return this.isValid ? this.ts : NaN - } - - /** - * Returns the epoch seconds of this DateTime. - * @return {number} - */ - toSeconds() { - return this.isValid ? this.ts / 1000 : NaN - } - - /** - * Returns the epoch seconds (as a whole number) of this DateTime. - * @return {number} - */ - toUnixInteger() { - return this.isValid ? Math.floor(this.ts / 1000) : NaN - } - - /** - * Returns an ISO 8601 representation of this DateTime appropriate for use in JSON. - * @return {string} - */ - toJSON() { - return this.toISO() - } - - /** - * Returns a BSON serializable equivalent to this DateTime. - * @return {Date} - */ - toBSON() { - return this.toJSDate() - } - - /** - * Returns a JavaScript object with this DateTime's year, month, day, and so on. - * @param opts - options for generating the object - * @param {boolean} [opts.includeConfig=false] - include configuration attributes in the output - * @example DateTime.now().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 } - * @return {Object} - */ - toObject(opts = {}) { - if (!this.isValid) return {} - - const base = { ...this.c } - - if (opts.includeConfig) { - base.outputCalendar = this.outputCalendar - base.numberingSystem = this.loc.numberingSystem - base.locale = this.loc.locale - } - return base - } - - /** - * Returns a JavaScript Date equivalent to this DateTime. - * @return {Date} - */ - toJSDate() { - return new Date(this.isValid ? this.ts : NaN) - } - - // COMPARE - - /** - * Return the difference between two DateTimes as a Duration. - * @param {DateTime} otherDateTime - the DateTime to compare this one to - * @param {string|string[]} [unit=['milliseconds']] - the unit or array of units (such as 'hours' or 'days') to include in the duration. - * @param {Object} opts - options that affect the creation of the Duration - * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use - * @example - * var i1 = DateTime.fromISO('1982-05-25T09:45'), - * i2 = DateTime.fromISO('1983-10-14T10:30'); - * i2.diff(i1).toObject() //=> { milliseconds: 43807500000 } - * i2.diff(i1, 'hours').toObject() //=> { hours: 12168.75 } - * i2.diff(i1, ['months', 'days']).toObject() //=> { months: 16, days: 19.03125 } - * i2.diff(i1, ['months', 'days', 'hours']).toObject() //=> { months: 16, days: 19, hours: 0.75 } - * @return {Duration} - */ - diff(otherDateTime, unit = 'milliseconds', opts = {}) { - if (!this.isValid || !otherDateTime.isValid) { - return Duration.invalid('created by diffing an invalid DateTime') - } - - const durOpts = { - locale: this.locale, - numberingSystem: this.numberingSystem, - ...opts, - } - - const units = maybeArray(unit).map(Duration.normalizeUnit), - otherIsLater = otherDateTime.valueOf() > this.valueOf(), - earlier = otherIsLater ? this : otherDateTime, - later = otherIsLater ? otherDateTime : this, - diffed = diff(earlier, later, units, durOpts) - - return otherIsLater ? diffed.negate() : diffed - } - - /** - * Return the difference between this DateTime and right now. - * See {@link DateTime#diff} - * @param {string|string[]} [unit=['milliseconds']] - the unit or units units (such as 'hours' or 'days') to include in the duration - * @param {Object} opts - options that affect the creation of the Duration - * @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use - * @return {Duration} - */ - diffNow(unit = 'milliseconds', opts = {}) { - return this.diff(DateTime.now(), unit, opts) - } - - /** - * Return an Interval spanning between this DateTime and another DateTime - * @param {DateTime} otherDateTime - the other end point of the Interval - * @return {Interval} - */ - until(otherDateTime) { - return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this - } - - /** - * Return whether this DateTime is in the same unit of time as another DateTime. - * Higher-order units must also be identical for this function to return `true`. - * Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link DateTime#setZone} to convert one of the dates if needed. - * @param {DateTime} otherDateTime - the other DateTime - * @param {string} unit - the unit of time to check sameness on - * @param {Object} opts - options - * @param {boolean} [opts.useLocaleWeeks=false] - If true, use weeks based on the locale, i.e. use the locale-dependent start of the week; only the locale of this DateTime is used - * @example DateTime.now().hasSame(otherDT, 'day'); //~> true if otherDT is in the same current calendar day - * @return {boolean} - */ - hasSame(otherDateTime, unit, opts) { - if (!this.isValid) return false - - const inputMs = otherDateTime.valueOf() - const adjustedToZone = this.setZone(otherDateTime.zone, { - keepLocalTime: true, - }) - return ( - adjustedToZone.startOf(unit, opts) <= inputMs && - inputMs <= adjustedToZone.endOf(unit, opts) - ) - } - - /** - * Equality check - * Two DateTimes are equal if and only if they represent the same millisecond, have the same zone and location, and are both valid. - * To compare just the millisecond values, use `+dt1 === +dt2`. - * @param {DateTime} other - the other DateTime - * @return {boolean} - */ - equals(other) { - return ( - this.isValid && - other.isValid && - this.valueOf() === other.valueOf() && - this.zone.equals(other.zone) && - this.loc.equals(other.loc) - ) - } - - /** - * Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your - * platform supports Intl.RelativeTimeFormat. Rounds down by default. - * @param {Object} options - options that affect the output - * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now. - * @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow" - * @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds" - * @param {boolean} [options.round=true] - whether to round the numbers in the output. - * @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding. - * @param {string} options.locale - override the locale of this DateTime - * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this - * @example DateTime.now().plus({ days: 1 }).toRelative() //=> "in 1 day" - * @example DateTime.now().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día" - * @example DateTime.now().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures" - * @example DateTime.now().minus({ days: 2 }).toRelative() //=> "2 days ago" - * @example DateTime.now().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago" - * @example DateTime.now().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago" - */ - toRelative(options = {}) { - if (!this.isValid) return null - const base = options.base || DateTime.fromObject({}, { zone: this.zone }), - padding = options.padding - ? this < base - ? -options.padding - : options.padding - : 0 - let units = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'] - let unit = options.unit - if (Array.isArray(options.unit)) { - units = options.unit - unit = undefined - } - return diffRelative(base, this.plus(padding), { - ...options, - numeric: 'always', - units, - unit, - }) - } - - /** - * Returns a string representation of this date relative to today, such as "yesterday" or "next month". - * Only internationalizes on platforms that supports Intl.RelativeTimeFormat. - * @param {Object} options - options that affect the output - * @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now. - * @param {string} options.locale - override the locale of this DateTime - * @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", or "days" - * @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this - * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow" - * @example DateTime.now().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana" - * @example DateTime.now().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain" - * @example DateTime.now().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago" - */ - toRelativeCalendar(options = {}) { - if (!this.isValid) return null - - return diffRelative( - options.base || DateTime.fromObject({}, { zone: this.zone }), - this, - { - ...options, - numeric: 'auto', - units: ['years', 'months', 'days'], - calendary: true, - } - ) - } - - /** - * Return the min of several date times - * @param {...DateTime} dateTimes - the DateTimes from which to choose the minimum - * @return {DateTime} the min DateTime, or undefined if called with no argument - */ - static min(...dateTimes) { - if (!dateTimes.every(DateTime.isDateTime)) { - throw new InvalidArgumentError('min requires all arguments be DateTimes') - } - return bestBy(dateTimes, (i) => i.valueOf(), Math.min) - } - - /** - * Return the max of several date times - * @param {...DateTime} dateTimes - the DateTimes from which to choose the maximum - * @return {DateTime} the max DateTime, or undefined if called with no argument - */ - static max(...dateTimes) { - if (!dateTimes.every(DateTime.isDateTime)) { - throw new InvalidArgumentError('max requires all arguments be DateTimes') - } - return bestBy(dateTimes, (i) => i.valueOf(), Math.max) - } - - // MISC - - /** - * Explain how a string would be parsed by fromFormat() - * @param {string} text - the string to parse - * @param {string} fmt - the format the string is expected to be in (see description) - * @param {Object} options - options taken by fromFormat() - * @return {Object} - */ - static fromFormatExplain(text, fmt, options = {}) { - const { locale = null, numberingSystem = null } = options, - localeToUse = Locale.fromOpts({ - locale, - numberingSystem, - defaultToEN: true, - }) - return explainFromTokens(localeToUse, text, fmt) - } - - /** - * @deprecated use fromFormatExplain instead - */ - static fromStringExplain(text, fmt, options = {}) { - return DateTime.fromFormatExplain(text, fmt, options) - } - - // FORMAT PRESETS - - /** - * {@link DateTime#toLocaleString} format like 10/14/1983 - * @type {Object} - */ - static get DATE_SHORT() { - return DATE_SHORT - } - - /** - * {@link DateTime#toLocaleString} format like 'Oct 14, 1983' - * @type {Object} - */ - static get DATE_MED() { - return DATE_MED - } - - /** - * {@link DateTime#toLocaleString} format like 'Fri, Oct 14, 1983' - * @type {Object} - */ - static get DATE_MED_WITH_WEEKDAY() { - return DATE_MED_WITH_WEEKDAY - } - - /** - * {@link DateTime#toLocaleString} format like 'October 14, 1983' - * @type {Object} - */ - static get DATE_FULL() { - return DATE_FULL - } - - /** - * {@link DateTime#toLocaleString} format like 'Tuesday, October 14, 1983' - * @type {Object} - */ - static get DATE_HUGE() { - return DATE_HUGE - } - - /** - * {@link DateTime#toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get TIME_SIMPLE() { - return TIME_SIMPLE - } - - /** - * {@link DateTime#toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get TIME_WITH_SECONDS() { - return TIME_WITH_SECONDS - } - - /** - * {@link DateTime#toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is. - * @type {Object} - */ - static get TIME_WITH_SHORT_OFFSET() { - return TIME_WITH_SHORT_OFFSET - } - - /** - * {@link DateTime#toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is. - * @type {Object} - */ - static get TIME_WITH_LONG_OFFSET() { - return TIME_WITH_LONG_OFFSET - } - - /** - * {@link DateTime#toLocaleString} format like '09:30', always 24-hour. - * @type {Object} - */ - static get TIME_24_SIMPLE() { - return TIME_24_SIMPLE - } - - /** - * {@link DateTime#toLocaleString} format like '09:30:23', always 24-hour. - * @type {Object} - */ - static get TIME_24_WITH_SECONDS() { - return TIME_24_WITH_SECONDS - } - - /** - * {@link DateTime#toLocaleString} format like '09:30:23 EDT', always 24-hour. - * @type {Object} - */ - static get TIME_24_WITH_SHORT_OFFSET() { - return TIME_24_WITH_SHORT_OFFSET - } - - /** - * {@link DateTime#toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour. - * @type {Object} - */ - static get TIME_24_WITH_LONG_OFFSET() { - return TIME_24_WITH_LONG_OFFSET - } - - /** - * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_SHORT() { - return DATETIME_SHORT - } - - /** - * {@link DateTime#toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_SHORT_WITH_SECONDS() { - return DATETIME_SHORT_WITH_SECONDS - } - - /** - * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_MED() { - return DATETIME_MED - } - - /** - * {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_MED_WITH_SECONDS() { - return DATETIME_MED_WITH_SECONDS - } - - /** - * {@link DateTime#toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_MED_WITH_WEEKDAY() { - return DATETIME_MED_WITH_WEEKDAY - } - - /** - * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_FULL() { - return DATETIME_FULL - } - - /** - * {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_FULL_WITH_SECONDS() { - return DATETIME_FULL_WITH_SECONDS - } - - /** - * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_HUGE() { - return DATETIME_HUGE - } - - /** - * {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is. - * @type {Object} - */ - static get DATETIME_HUGE_WITH_SECONDS() { - return DATETIME_HUGE_WITH_SECONDS - } -} - -/** - * @private - */ -function friendlyDateTime(dateTimeish) { - if (DateTime.isDateTime(dateTimeish)) { - return dateTimeish - } else if ( - dateTimeish && - dateTimeish.valueOf && - isNumber(dateTimeish.valueOf()) - ) { - return DateTime.fromJSDate(dateTimeish) - } else if (dateTimeish && typeof dateTimeish === 'object') { - return DateTime.fromObject(dateTimeish) - } else { - throw new InvalidArgumentError( - `Unknown datetime argument: ${dateTimeish}, of type ${typeof dateTimeish}` - ) - } -} - -const VERSION = '3.4.4' - -export { - DateTime, - Duration, - FixedOffsetZone, - IANAZone, - Info, - Interval, - InvalidZone, - Settings, - SystemZone, - VERSION, - Zone, -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/metadata.json deleted file mode 100644 index 6ef6e211..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/metadata.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Allows customization of the date display in the panel.\n\nMight be especially useful if you're using a horizontal panel which does not at all work well with the default date display.\n\nCHANGELOG\nVersion 5: added support for multiple Dash To Panel panels\nVersion 6: fixed issues on earlier Gnome Shell versions\nVersion 10: fixed clock hover style (by bomdia)\nVersion 11: Gnome 45 update by andyholmes@github\nVersion 12: added support for advanced formatters by bomdia@github\nVersion 15: added text alignment choice by bomdia@github", - "gettext-domain": "date-menu-formatter", - "name": "Date Menu Formatter", - "settings-schema": "org.gnome.shell.extensions.date-menu-formatter", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/marcinjakubowski/date-menu-formatter", - "uuid": "date-menu-formatter@marcinjakubowski.github.com", - "version": 15 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/prefs.js deleted file mode 100644 index 043c4efc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/prefs.js +++ /dev/null @@ -1,558 +0,0 @@ -/* extension.js - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -/* - Swaths of pref related code borrowed from Clipboard Indicator, an amazing extension - https://github.com/Tudmotu/gnome-shell-extension-clipboard-indicator - https://extensions.gnome.org/extension/779/clipboard-indicator/ -*/ -import Gio from 'gi://Gio' -import Gtk from 'gi://Gtk?version=4.0' -import Adw from 'gi://Adw' - -import { - ExtensionPreferences, - gettext as _, -} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js' - -import * as prefFields from './utils/prefFields.js' -import { - getCurrentCalendar, - getCurrentTimezone, - getCurrentLocale, - updateLevelToString, - TEXT_ALIGN_START, - TEXT_ALIGN_CENTER, - TEXT_ALIGN_END, -} from './utils/general.js' -import { useAddRow, createLabel, addBox, table, a, b } from './utils/markup.js' -import { CALENDAR_LIST, FormatterManager } from './utils/formatter.js' - -class Preferences { - constructor(settings) { - this.settings = settings - this.formatters = new FormatterManager() - this._previewErrorCount = 0 - this.box = {} - this.initUI() - this.formatters - .loadFormatters() - .then(() => { - this.createUI() - this.UIShowHideFormatterAbility( - this.formatters.getFormatter(this._formatter.active_id).can - ) - this.generatePreview() - }) - .catch((e) => { - console.error('Date Menu Formatter error:', e) - }) - } - - initUI() { - this.main = new Gtk.Grid({ - margin_top: 10, - margin_bottom: 10, - margin_start: 10, - margin_end: 10, - row_spacing: 12, - column_spacing: 18, - column_homogeneous: false, - row_homogeneous: false, - }) - this.addRow = useAddRow(this.main) - this.addSeparator = () => this.addRow(null, new Gtk.Separator()) - } - - createUI() { - this.UIcreateFormatterSetting() - this.UIcreateFontSizeSetting() - this.UIcreateTextAlignSetting() - this.UIcreatePatternSetting() - this.UIcreatePatternPreview() - this.addSeparator() - this.UIcreateUpdateLevelSetting() - this.UIcreateDefaultLocaleSetting() - this.UIcreateDefaultCalendarSetting() - this.UIcreateDefaultTimezoneSetting() - this.addSeparator() - this.UIcreateRemoveUnreadMessagesSetting() - this.UIcreateAllPanelsSetting() - this.addSeparator() - this.UIcreateFormatterHelp() - } - - UIcreateFormatterSetting() { - const formatterSelect = new Gtk.ComboBoxText({ - hexpand: true, - halign: Gtk.Align.FILL, - }) - - this.formatters.asList().forEach(({ key, name }) => { - formatterSelect.append(key, name) - }) - - formatterSelect.set_active_id( - this.settings.get_string(prefFields.FORMATTER) - ) - this._formatter = formatterSelect - this.addRow(createLabel(_('Formatter')), formatterSelect) - - this.settings.bind( - prefFields.FORMATTER, - formatterSelect, - 'active-id', - Gio.SettingsBindFlags.DEFAULT - ) - formatterSelect.connect('changed', () => { - this.setHelpMarkup( - this.formatters.getFormatterHelp(this._formatter.active_id) - ) - this.UIShowHideFormatterAbility( - this.formatters.getFormatter(this._formatter.active_id).can - ) - this.generatePreview() - }) - } - - UIShowHideFormatterAbility(can) { - this.box.locale(can.customLocale) - this.box.calendar(can.customCalendar) - this.box.timezone(can.customTimezone) - } - - UIcreatePatternSetting() { - const patternEdit = new Gtk.Entry({ buffer: new Gtk.EntryBuffer() }) - - this.addRow(createLabel(_('Pattern')), patternEdit) - this._pattern = patternEdit.buffer - - this.settings.bind( - prefFields.PATTERN, - patternEdit.buffer, - 'text', - Gio.SettingsBindFlags.DEFAULT - ) - patternEdit.buffer.connect_after( - 'inserted-text', - this.generatePreview.bind(this) - ) - patternEdit.buffer.connect_after( - 'deleted-text', - this.generatePreview.bind(this) - ) - } - - UIcreatePatternPreview() { - this._preview = createLabel('') - this._preview.set_use_markup(true) - this.addRow(createLabel(_('Preview')), this._preview) - } - - UIcreateUpdateLevelSetting() { - const updateLevelSelect = new Gtk.ComboBoxText({ - hexpand: true, - halign: Gtk.Align.FILL, - }) - - for (let i = 0; i <= 15; i++) { - updateLevelSelect.append('' + i, updateLevelToString(i)) - } - updateLevelSelect.set_active_id( - '' + this.settings.get_int(prefFields.UPDATE_LEVEL) - ) - this.addRow(createLabel(_('Update')), updateLevelSelect) - - updateLevelSelect.connect('changed', () => { - this.settings.set_int( - prefFields.UPDATE_LEVEL, - parseInt(updateLevelSelect.active_id) - ) - }) - } - - UIcreateDefaultLocaleSetting() { - const useDefaultLocaleLabel = createLabel( - _('Use default locale') + ` (${getCurrentLocale()})` - ) - const localeBox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 30, - }) - const useDefaultLocaleEdit = new Gtk.Switch({ - vexpand: false, - valign: Gtk.Align.CENTER, - }) - const customLocaleEdit = new Gtk.Entry({ buffer: new Gtk.EntryBuffer() }) - addBox(localeBox, useDefaultLocaleEdit) - addBox(localeBox, customLocaleEdit) - - this.addRow(useDefaultLocaleLabel, localeBox) - - this.box.locale = (show) => { - if (show) { - localeBox.show() - useDefaultLocaleLabel.show() - } else { - localeBox.hide() - useDefaultLocaleLabel.hide() - } - } - this._customLocale = customLocaleEdit.buffer - this._useDefaultLocale = useDefaultLocaleEdit - - this.settings.bind( - prefFields.USE_DEFAULT_LOCALE, - useDefaultLocaleEdit, - 'active', - Gio.SettingsBindFlags.DEFAULT - ) - - this.settings.bind( - prefFields.USE_DEFAULT_LOCALE, - customLocaleEdit, - 'sensitive', - Gio.SettingsBindFlags.GET | - Gio.SettingsBindFlags.NO_SENSITIVITY | - Gio.SettingsBindFlags.INVERT_BOOLEAN - ) - - this.settings.bind( - prefFields.CUSTOM_LOCALE, - customLocaleEdit.buffer, - 'text', - Gio.SettingsBindFlags.DEFAULT - ) - - useDefaultLocaleEdit.connect('state-set', this.generatePreview.bind(this)) - customLocaleEdit.buffer.connect_after( - 'inserted-text', - this.generatePreview.bind(this) - ) - customLocaleEdit.buffer.connect_after( - 'deleted-text', - this.generatePreview.bind(this) - ) - } - UIcreateDefaultCalendarSetting() { - const defaultCalendarName = CALENDAR_LIST.find( - ({ key }) => key === getCurrentCalendar() - ).name - - const useDefaultCalendarLabel = createLabel( - _('Use default calendar') + ` (${defaultCalendarName})` - ) - const calendarBox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 30, - }) - const useDefaultCalendarEdit = new Gtk.Switch({ - vexpand: false, - valign: Gtk.Align.CENTER, - }) - const customCalendarSelect = new Gtk.ComboBoxText({ - hexpand: false, - halign: Gtk.Align.FILL, - }) - - CALENDAR_LIST.forEach(({ key, name, description }) => { - customCalendarSelect.append(key, `${name} -> "${description}"`) - }) - - customCalendarSelect.set_active_id( - this.settings.get_string(prefFields.CUSTOM_CALENDAR) || - getCurrentCalendar() - ) - - addBox(calendarBox, useDefaultCalendarEdit) - addBox(calendarBox, customCalendarSelect) - - this.addRow(useDefaultCalendarLabel, calendarBox) - - this.box.calendar = (show) => { - if (show) { - calendarBox.show() - useDefaultCalendarLabel.show() - } else { - calendarBox.hide() - useDefaultCalendarLabel.hide() - } - } - this._customCalendar = customCalendarSelect - this._useDefaultCalendar = useDefaultCalendarEdit - - this.settings.bind( - prefFields.USE_DEFAULT_CALENDAR, - useDefaultCalendarEdit, - 'active', - Gio.SettingsBindFlags.DEFAULT - ) - this.settings.bind( - prefFields.CUSTOM_CALENDAR, - customCalendarSelect, - 'active-id', - Gio.SettingsBindFlags.DEFAULT - ) - this.settings.bind( - prefFields.USE_DEFAULT_CALENDAR, - customCalendarSelect, - 'sensitive', - Gio.SettingsBindFlags.GET | - Gio.SettingsBindFlags.NO_SENSITIVITY | - Gio.SettingsBindFlags.INVERT_BOOLEAN - ) - useDefaultCalendarEdit.connect('state-set', this.generatePreview.bind(this)) - customCalendarSelect.connect('changed', this.generatePreview.bind(this)) - } - - UIcreateDefaultTimezoneSetting() { - const useDefaultTimezoneLabel = createLabel( - _('Use default timezone') + ` (${getCurrentTimezone()})` - ) - const timezoneBox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 30, - }) - const useDefaultTimezoneEdit = new Gtk.Switch({ - vexpand: false, - valign: Gtk.Align.CENTER, - }) - - const customTimezoneEdit = new Gtk.Entry({ buffer: new Gtk.EntryBuffer() }) - - addBox(timezoneBox, useDefaultTimezoneEdit) - addBox(timezoneBox, customTimezoneEdit) - - this.addRow(useDefaultTimezoneLabel, timezoneBox) - - this.box.timezone = (show) => { - if (show) { - timezoneBox.show() - useDefaultTimezoneLabel.show() - } else { - timezoneBox.hide() - useDefaultTimezoneLabel.hide() - } - } - this._customTimezone = customTimezoneEdit.buffer - this._useDefaultTimezone = useDefaultTimezoneEdit - - this.settings.bind( - prefFields.USE_DEFAULT_TIMEZONE, - useDefaultTimezoneEdit, - 'active', - Gio.SettingsBindFlags.DEFAULT - ) - this.settings.bind( - prefFields.CUSTOM_TIMEZONE, - customTimezoneEdit.buffer, - 'text', - Gio.SettingsBindFlags.DEFAULT - ) - this.settings.bind( - prefFields.USE_DEFAULT_TIMEZONE, - customTimezoneEdit, - 'sensitive', - Gio.SettingsBindFlags.GET | - Gio.SettingsBindFlags.NO_SENSITIVITY | - Gio.SettingsBindFlags.INVERT_BOOLEAN - ) - - useDefaultTimezoneEdit.connect('state-set', this.generatePreview.bind(this)) - - customTimezoneEdit.buffer.connect_after( - 'inserted-text', - this.generatePreview.bind(this) - ) - customTimezoneEdit.buffer.connect_after( - 'deleted-text', - this.generatePreview.bind(this) - ) - } - - UIcreateRemoveUnreadMessagesSetting() { - const removeMessagesIndicatorEdit = new Gtk.Switch() - this.addRow( - createLabel(_('Remove unread messages indicator')), - removeMessagesIndicatorEdit - ) - - this.settings.bind( - prefFields.REMOVE_MESSAGES_INDICATOR, - removeMessagesIndicatorEdit, - 'active', - Gio.SettingsBindFlags.DEFAULT - ) - } - - UIcreateAllPanelsSetting() { - const applyAllPanelsEdit = new Gtk.Switch() - - this.addRow( - createLabel(_('Apply to all panels (Dash to Panel)')), - applyAllPanelsEdit - ) - this.settings.bind( - prefFields.APPLY_ALL_PANELS, - applyAllPanelsEdit, - 'active', - Gio.SettingsBindFlags.DEFAULT - ) - } - - UIcreateFontSizeSetting() { - const fontSizeEdit = new Gtk.SpinButton({ - adjustment: new Gtk.Adjustment({ - lower: 4, - upper: 30, - step_increment: 1, - }), - }) - - this.addRow(createLabel(_('Font size')), fontSizeEdit) - - fontSizeEdit.connect( - 'output', - function (spin) { - spin.text = `${spin.value} pt` - this.FONT_SIZE = spin.value - return true - }.bind(this) - ) - this.settings.bind( - prefFields.FONT_SIZE, - fontSizeEdit, - 'value', - Gio.SettingsBindFlags.DEFAULT - ) - } - UIcreateTextAlignSetting() { - const tAlignBox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 0, - }) - tAlignBox.set_css_classes(['linked']) - - const buttons = [ - { - btn: Gtk.Button.new_from_icon_name('format-justify-left-symbolic'), - key: TEXT_ALIGN_START, - }, - { - btn: Gtk.Button.new_from_icon_name('format-justify-center-symbolic'), - key: TEXT_ALIGN_CENTER, - }, - { - btn: Gtk.Button.new_from_icon_name('format-justify-right-symbolic'), - key: TEXT_ALIGN_END, - }, - ] - const settings = this.settings - const selected = { - get value() { - return settings.get_string(prefFields.TEXT_ALIGN) - }, - set value(sel) { - buttons.forEach(({ btn, key }) => { - btn.set_sensitive(key !== sel) - }) - settings.set_string(prefFields.TEXT_ALIGN, sel) - }, - } - selected.value = selected.value || TEXT_ALIGN_CENTER - buttons.forEach(({ btn, key }) => { - addBox(tAlignBox, btn) - btn.connect('clicked', function () { - selected.value = key - }) - }) - - this.addRow(createLabel(_('Align Text')), tAlignBox) - } - - UIcreateFormatterHelp() { - const left = createLabel('') - const right = createLabel('') - - this.setHelpMarkup = (help) => { - left.set_markup(`${b('Available pattern components')}${table(help.left)}`) - right.set_markup(`${a(help.link, 'Full list (web)')}${table(help.right)}`) - } - - this.setHelpMarkup( - this.formatters.getFormatterHelp(this._formatter.active_id) - ) - - this.addRow(left, right) - } - - generatePreview() { - const locale = this._useDefaultLocale.active - ? getCurrentLocale() - : this._customLocale.text - const calendar = this._useDefaultCalendar.active - ? getCurrentCalendar() - : this._customCalendar.active_id - const timezone = this._useDefaultTimezone.active - ? getCurrentTimezone() - : this._customTimezone.text - - if (this._pattern.text.length > 1) { - try { - const formatter = this.formatters.getFormatter( - this._formatter.active_id - ) - this._preview.label = new formatter(timezone, locale, calendar).format( - this._pattern.text, - new Date() - ) - this._previewErrorCount = 0 - } catch (e) { - this._previewErrorCount++ - if (this._previewErrorCount > 2) { - this._preview.label = 'ERROR: ' + e.message - } - } - } else { - this._preview.label = '' - this._previewErrorCount = 0 - } - } -} - -export default class DateMenuFormatterPreferences extends ExtensionPreferences { - getPreferencesWidget() { - const frame = new Gtk.Box() - const widget = new Preferences(this.getSettings()) - addBox(frame, widget.main) - if (frame.show_all) frame.show_all() - return frame - } - fillPreferencesWindow(window) { - window._settings = this.getSettings() - window.set_size_request(1000, 700) - const page = new Adw.PreferencesPage() - - const group = new Adw.PreferencesGroup({ - title: _('General'), - }) - group.add(this.getPreferencesWidget()) - page.add(group) - window.add(page) - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/schemas/gschemas.compiled deleted file mode 100644 index 696ac0af..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/schemas/org.gnome.shell.extensions.date-menu-formatter.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/schemas/org.gnome.shell.extensions.date-menu-formatter.gschema.xml deleted file mode 100644 index 1eadd3a6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/schemas/org.gnome.shell.extensions.date-menu-formatter.gschema.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - "01_luxon" - Date formatter - - - - "EEE, MMM d H : mm" - Date format pattern - - - - "" - Custom locale - - - - true - Should default system locale be used - - - - "" - Custom Calendar - - - - true - Should default calendar be used - - - - "" - Custom timezone - - - - true - Should default system timezone be used - - - - false - Should unread messages indicator be removed - - - - false - Should extension modify all Dash To Panel panels - - - - 10 - Font size - - - - 1 - Update Clock Every - - 0 = every minute - 1 = every seconds - 2 = 2 time in a second - 3 = 3 time in a second - 4 = 4 time in a second - 5 = 5 time in a second - 6 = 6 time in a second - 7 = 7 time in a second - 8 = 8 time in a second - 9 = 9 time in a second - 10 = 10 time in a second - 11 = 11 time in a second - 12 = 12 time in a second - 13 = 13 time in a second - 14 = 14 time in a second - 15 = 15 time in a second - - - - "center" - Align the label - - left - center - right - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils.js deleted file mode 100644 index 9a4be198..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils.js +++ /dev/null @@ -1,27 +0,0 @@ -var PrefFields = { - PATTERN : 'pattern', - USE_DEFAULT_LOCALE : 'use-default-locale', - CUSTOM_LOCALE : 'custom-locale', - FONT_SIZE : 'font-size', - APPLY_ALL_PANELS : 'apply-all-panels', - REMOVE_MESSAGES_INDICATOR: 'remove-messages-indicator' -}; - -function getCurrentLocale() { - return (new Intl.DateTimeFormat()).resolvedOptions().locale -} - -function convertToPattern(str) { - return '#' + str.replace(new RegExp("\\\\n", "g"), "\n").replace(new RegExp("''", "g"), ">`<") -} - -function convertFromPattern(str) { - return str.replace(new RegExp('>`<', "g"), "'") -} - -export { - PrefFields, - getCurrentLocale, - convertToPattern, - convertFromPattern, -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/formatter.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/formatter.js deleted file mode 100644 index e4df4859..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/formatter.js +++ /dev/null @@ -1,108 +0,0 @@ -import { importDir } from '../lib/importDir.js' - -export class BaseFormatter { - constructor(timezone, locale, calendar) { - this.config(timezone, locale, calendar) - } - - config(timezone, locale, calendar) {} - - format(pattern, date) {} -} - -export function createFormatter( - formatterLabel, - formatterDescription, - { customTimezone, customLocale, customCalendar } = {} -) { - return class CustomFormatter extends BaseFormatter { - static label = formatterLabel || '' - static description = formatterDescription || '' - static can = Object.freeze({ - customTimezone: !!customTimezone, - customLocale: !!customLocale, - customCalendar: !!customCalendar, - }) - } -} - -function freeze(arr) { - if (!Array.isArray(arr)) return Object.freeze([]) - for (let i = 0; i < arr.length; i++) { - arr[i] = Object.freeze(arr[i]) - } - return Object.freeze(arr) -} - -export class FormatterHelp { - #link - #left - #right - constructor(link, left, right) { - this.#link = typeof link === 'string' && link !== '' ? link : '' - this.#left = freeze(left) - this.#right = freeze(right) - } - get link() { - return this.#link - } - get left() { - return this.#left - } - get right() { - return this.#right - } -} - -export class FormatterManager { - constructor(load = false) { - this.formatters = {} - if (load) this.loadFormatters() - } - async loadFormatters() { - this.formatters = await importDir([import.meta.url, '../formatters']) - return this.formatters - } - - getFormatter(key) { - return this.formatters[key] ? this.formatters[key].default : undefined - } - getFormatterHelp(key) { - return this.formatters[key] ? this.formatters[key].help() : undefined - } - - asList() { - return Object.keys(this.formatters) - .filter((f) => !f.startsWith('_')) - .map((f) => ({ - key: f, - name: this.getFormatter(f).label, - description: this.getFormatter(f).description, - })) - } -} - -export const CALENDAR_LIST = [ - { key: 'gregory', description: '1 March 2010', name: 'Gregorian' }, - { key: 'buddhist', description: 'September 24, 2560 BE', name: 'Buddhist' }, - { key: 'chinese', description: 'Eighth Month 5, 2017', name: 'Chinese' }, - { key: 'coptic', description: 'Tout 14, 1734 ERA1', name: 'Coptic' }, - { - key: 'ethioaa', - description: 'Meskerem 14, 7510 ERA0', - name: 'Ethiopic (Amete Alem)', - }, - { key: 'ethiopic', description: 'Meskerem 14, 2010 ERA1', name: 'Ethiopic' }, - { key: 'hebrew', description: '4 Tishri 5778', name: 'Hebrew' }, - { key: 'indian', description: 'Asvina 2, 1939 Saka', name: 'Indian' }, - { key: 'islamic', description: 'Muharram 4, 1439 AH', name: 'Islamic' }, - { - key: 'islamic-civil', - description: 'Muharram 3, 1439 AH', - name: 'Islamic Civil', - }, - { key: 'iso8601', description: 'September 24, 2017', name: 'ISO 8601' }, - { key: 'japanese', description: 'September 24, 29 Heisei', name: 'Japanase' }, - { key: 'persian', description: 'Mehr 2, 1396 AP', name: 'Persian' }, - { key: 'roc', description: 'September 24, 106 Minguo', name: 'Minguo' }, -] diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/general.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/general.js deleted file mode 100644 index 4a8e6dba..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/general.js +++ /dev/null @@ -1,40 +0,0 @@ -import GLib from 'gi://GLib' - -export const TEXT_ALIGN_START = 'left' -export const TEXT_ALIGN_CENTER = 'center' -export const TEXT_ALIGN_END = 'right' - -function currentOptions() { - return new Intl.DateTimeFormat().resolvedOptions() -} - -export function getCurrentLocale() { - return currentOptions().locale -} -export function getCurrentTimezone() { - return currentOptions().timeZone -} -export function getCurrentCalendar() { - return currentOptions().calendar -} - -export function updateLevel(lvl) { - if (typeof lvl === 'number' && !Number.isNaN(lvl)) { - if (lvl === 0) - return { lvl, priority: GLib.PRIORITY_DEFAULT_IDLE, timeout: 1000 * 60 } - if (lvl > 0 && lvl <= 7) - return { lvl, priority: GLib.PRIORITY_DEFAULT, timeout: 1000 / lvl } - if (lvl > 7 && lvl <= 15) - return { lvl, priority: GLib.PRIORITY_HIGH, timeout: 1000 / lvl } - } - return { lvl: 1, priority: GLib.PRIORITY_DEFAULT, timeout: 1000 } -} - -export function updateLevelToString(lvl) { - if (typeof lvl === 'number' && !Number.isNaN(lvl)) { - if (lvl === 0) return `every minute` - if (lvl === 1) return `every second` - if (lvl > 1 && lvl <= 15) return `${lvl} times in a second` - } - return `every second` -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/markup.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/markup.js deleted file mode 100644 index 223aa8e2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/markup.js +++ /dev/null @@ -1,72 +0,0 @@ -import Gtk from 'gi://Gtk' -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js' - -function findPadSize(rows) { - let maxSize = [] - for (const row of rows) { - row.forEach((col, i) => { - if (typeof maxSize[i] !== 'number') maxSize[i] = 0 - if (col.length > maxSize[i]) maxSize[i] = col.length - }) - } - return maxSize -} -function row(value, desc, ex) { - return `|${value} | ${_(desc)} | ${_( - ex - )}\n` -} - -export function table(rows) { - const [patternPad, descriptionPad, examplePad] = findPadSize(rows) - return `\n\n${rows.reduce( - (acc, [pattern, description, example]) => - acc + - row( - pattern.padEnd(patternPad), - description.padEnd(descriptionPad), - example.padStart(examplePad) - ), - '' - )}` -} -export function a(ref, label) { - return ref ? `${_(label)}` : '' -} -export function b(label) { - return `${_(label)}` -} - -export function addBox(box, child) { - box.append(child) -} - -export function useAddRow(main) { - let row = 0 - return (label, input) => { - let inputWidget = input - - if (input instanceof Gtk.Switch) { - inputWidget = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL }) - addBox(inputWidget, input) - } - - if (label) { - main.attach(label, 0, row, 1, 1) - if (inputWidget) main.attach(inputWidget, 1, row, 1, 1) - } else { - main.attach(inputWidget, 0, row, 2, 1) - } - - row++ - return row - 1 - } -} - -export function createLabel(label) { - return new Gtk.Label({ - label: label, - hexpand: true, - halign: Gtk.Align.START, - }) -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/prefFields.js b/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/prefFields.js deleted file mode 100644 index 00c6bb27..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/date-menu-formatter@marcinjakubowski.github.com/utils/prefFields.js +++ /dev/null @@ -1,13 +0,0 @@ -export const FORMATTER = 'formatter' -export const PATTERN = 'pattern' -export const UPDATE_LEVEL = 'update-level' -export const USE_DEFAULT_LOCALE = 'use-default-locale' -export const CUSTOM_LOCALE = 'custom-locale' -export const USE_DEFAULT_CALENDAR = 'use-default-calendar' -export const CUSTOM_CALENDAR = 'custom-calendar' -export const USE_DEFAULT_TIMEZONE = 'use-default-timezone' -export const CUSTOM_TIMEZONE = 'custom-timezone' -export const FONT_SIZE = 'font-size' -export const APPLY_ALL_PANELS = 'apply-all-panels' -export const REMOVE_MESSAGES_INDICATOR = 'remove-messages-indicator' -export const TEXT_ALIGN = 'text-align' diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/LICENSE b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/LICENSE deleted file mode 100755 index f288702d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/extension.js deleted file mode 100755 index 79d8ded3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/extension.js +++ /dev/null @@ -1,1312 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // -// | \ | ( ` | / | / \ | ) / | | | ) | // -// | | |- `-. |< | | | |-' | | | |-< |- // -// | / | . ) | \ | \ / | \ | | | ) | // -// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // -////////////////////////////////////////////////////////////////////////////////////////// - -// SPDX-FileCopyrightText: Simon Schneegans -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import Gio from 'gi://Gio'; -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import Graphene from 'gi://Graphene'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Config from 'resource:///org/gnome/shell/misc/config.js'; -import {PressureBarrier} from 'resource:///org/gnome/shell/ui/layout.js'; -import {WorkspacesView, FitMode} from 'resource:///org/gnome/shell/ui/workspacesView.js'; -import {SwipeTracker} from 'resource:///org/gnome/shell/ui/swipeTracker.js'; -import {WorkspaceAnimationController} from 'resource:///org/gnome/shell/ui/workspaceAnimation.js'; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as utils from './src/utils.js'; -import {DragGesture} from './src/DragGesture.js'; -import {Skybox} from './src/Skybox.js'; - -////////////////////////////////////////////////////////////////////////////////////////// -// This extensions tweaks the positioning of workspaces in overview mode and while // -// switching workspaces in desktop mode to make them look like cube faces. // -////////////////////////////////////////////////////////////////////////////////////////// - -const [GS_VERSION] = Config.PACKAGE_VERSION.split('.').map(s => Number(s)); - -// Maximum degrees the cube can be rotated up and down. -const MAX_VERTICAL_ROTATION = 50; - -// Spacing to the screen sides of the vertically rotated cube. -const PADDING_V_ROTATION = 0.2; - -export default class DesktopCube extends Extension { - _lastWorkspaceWidth = 0; - - // ------------------------------------------------------------------------ public stuff - - // This function could be called after the extension is enabled, which could be done - // from GNOME Tweaks, when you log in or when the screen is unlocked. - enable() { - - // Store a reference to the settings object. - this._settings = this.getSettings(); - - // We will monkey-patch these methods. Let's store the original ones. - this._origEndGesture = SwipeTracker.prototype._endGesture; - this._origUpdateWorkspacesState = WorkspacesView.prototype._updateWorkspacesState; - this._origGetSpacing = WorkspacesView.prototype._getSpacing; - this._origUpdateVisibility = WorkspacesView.prototype._updateVisibility; - this._origPrepSwitch = WorkspaceAnimationController.prototype._prepareWorkspaceSwitch; - this._origFinalSwitch = WorkspaceAnimationController.prototype._finishWorkspaceSwitch; - - // We will use extensionThis to refer to the extension inside the patched methods. - const extensionThis = this; - - // ----------------------------------------------------------------------------------- - // ------------------------------- cubify the overview ------------------------------- - // ----------------------------------------------------------------------------------- - - // Normally, all workspaces outside the current field-of-view are hidden. We want to - // show all workspaces, so we patch this method. The original code is about here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L420 - WorkspacesView.prototype._updateVisibility = function() { - this._workspaces.forEach((w) => { - w.show(); - }); - }; - - // Usually, workspaces are placed next to each other separated by a few pixels (this - // separation is usually computed by the method below). To create the desktop cube, we - // have to position all workspaces on top of each other and rotate the around a pivot - // point in the center of the cube. - // The original arrangement of the workspaces is implemented in WorkspacesView's - // vfunc_allocate() which cannot be monkey-patched. As a workaround, we return a - // negative spacing in the method below... - // The original code is about here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L219 - WorkspacesView.prototype._getSpacing = function(box, fitMode, vertical) { - // We use the "normal" workspace spacing in desktop and app-grid mode. - const origValue = - extensionThis._origGetSpacing.apply(this, [box, fitMode, vertical]); - - if (fitMode == FitMode.ALL) { - return origValue; - } - - // Compute the negative spacing required to arrange workspaces on top of each other. - const overlapValue = -this._workspaces[0].get_preferred_width(box.get_size()[1])[1]; - - // Blend between the negative overlap-spacing and the "normal" spacing value. - const cubeMode = extensionThis._getCubeMode(this); - return Util.lerp(origValue, overlapValue, cubeMode); - }; - - // This is the main method which is called whenever the workspaces need to be - // repositioned. - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L255 - WorkspacesView.prototype._updateWorkspacesState = function() { - // Use the original method if we have just one workspace. - const faceCount = this._workspaces.length; - if (faceCount <= 1) { - extensionThis._origUpdateWorkspacesState.apply(this); - return; - } - - // Here's a minor hack to improve the performance: During the transitions to / from - // the app drawer, this._updateWorkspacesState is called twice a frame. Once from - // the notify handler of this._fitModeAdjustment and thereafter once from the notify - // handler of this._overviewAdjustment. As this seems not so useful (and degrades - // performance a lot), we skip the first call. I am not aware of any cases where - // this._fitModeAdjustment is changed without any of the over adjustments to change - // as well... - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L109 - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L45 - if ((new Error()).stack.includes('fitModeNotify')) { - return; - } - - // Compute blending state from and to the overview, from and to the app grid, and - // from and to the desktop mode. We will use cubeMode to fold and unfold the - // cube, overviewMode to add some depth between windows and backgrounds, and - // appDrawerMode to attenuate the scaling effect of the active workspace. - const appDrawerMode = extensionThis._getAppDrawerMode(this); - const overviewMode = extensionThis._getOverviewMode(this); - const cubeMode = extensionThis._getCubeMode(this); - - // First we need the width of a single workspace. Simply calling - // this._workspaces[0]._background.width does not work in all cases, as this method - // seems to be called also when the background actor is not on the stage. As a hacky - // workaround, we store the last valid workspace width we got and use that value if - // we cannot get a new one... - let workspaceWidth = extensionThis._lastWorkspaceWidth; - const bg = this._workspaces[0]._background; - if (bg.get_stage() && bg.allocation.get_width() > 0) { - workspaceWidth = bg.allocation.get_width(); - - // Add gaps between workspaces in overview mode. - workspaceWidth += - overviewMode * 2 * extensionThis._settings.get_int('workpace-separation'); - - extensionThis._lastWorkspaceWidth = workspaceWidth; - } - - // That's the angle between consecutive workspaces. - const faceAngle = extensionThis._getFaceAngle(faceCount); - - // That's the z-distance from the cube faces to the rotation pivot. - const centerDepth = extensionThis._getCenterDist(workspaceWidth, faceAngle); - - // Apply vertical rotation if required. This comes from the pitch value of the - // modified SwipeTracker created by _addOverviewDragGesture() further below. - this.pivot_point_z = -centerDepth; - this.set_pivot_point(0.5, 0.5); - this.rotation_angle_x = extensionThis._pitch.value * MAX_VERTICAL_ROTATION; - - // During rotations, the cube is scaled down and the windows are "exploded". If we - // are directly facing a cube side, the strengths of both effects are approaching - // zero. The strengths of both effects are small during horizontal rotations to make - // workspace-switching not so obtrusive. However, during vertical rotations, the - // effects are stronger. - const [depthOffset, explode] = extensionThis._getExplodeFactors( - this._scrollAdjustment.value, extensionThis._pitch.value, centerDepth, - this._monitorIndex); - - // Now loop through all workspace and compute the individual rotations. - this._workspaces.forEach((w, index) => { - // First update the corner radii. Corners are only rounded in overview. - w.stateAdjustment.value = overviewMode; - - // Now update the rotation of the cube face. The rotation center is -centerDepth - // units behind the front face. - w.pivot_point_z = -centerDepth; - - // Make cube smaller during rotations. - w.translation_z = -depthOffset; - - // The rotation angle is transitioned proportional to cubeMode^1.5. This slows - // down the rotation a bit closer to the desktop and to the app drawer. - w.rotation_angle_y = - Math.pow(cubeMode, 1.5) * (-this._scrollAdjustment.value + index) * faceAngle; - - // Distance to being the active workspace in [-1...0...1]. - const dist = Math.clamp(index - this._scrollAdjustment.value, -1, 1); - - // This moves next and previous workspaces a bit to the left and right. This - // ensures that we can actually see them if we look at the cube from the front. - // The value is set to zero if we have five or more workspaces. - if (faceCount <= 4) { - w.translation_x = - dist * overviewMode * extensionThis._settings.get_int('horizontal-stretch'); - } else { - w.translation_x = 0; - } - - // Update opacity only in overview mode. - const opacityA = extensionThis._settings.get_int('active-workpace-opacity'); - const opacityB = extensionThis._settings.get_int('inactive-workpace-opacity'); - const opacity = Util.lerp(opacityA, opacityB, Math.abs(dist)); - w._background.set_opacity(Util.lerp(255, opacity, overviewMode)); - - // Update workspace scale only in app grid mode. The 0.94 is supposed to be the - // same value as the WORKSPACE_INACTIVE_SCALE defined here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L21 - // As this is defined as 'const', we cannot access it here. But the exact value - // also not really matters... - const scale = Util.lerp(1, 0.94, Math.abs(dist) * appDrawerMode); - w.set_scale(scale, scale); - - // Now we add some depth separation between the window clones. If the explode - // factor becomes too small, the depth sorting becomes non-deterministic. - if (explode > 0.001) { - - const sortedActors = w._container.layout_manager._sortedWindows; - - // Distribute the window clones translation_z values between zero and - // explode. - sortedActors.forEach((windowActor, j) => { - windowActor.translation_z = explode * (j + 1) / sortedActors.length; - }); - - // Now sort the window clones according to the orthogonal distance of the actor - // planes to the camera. This ensures proper depth sorting among the window - // clones. - if (sortedActors.length > 1) { - extensionThis._depthSortWindowActors(w._container.get_children(), - this._monitorIndex); - } - } - - // Now we sort the children of the workspace (e.g. the background actor - // and the container for the window clones) by their orthogonal distance to the - // virtual camera. We add a tiny translation to the window-clone container to - // allow for proper sorting. - w._container.translation_z = 1; - extensionThis._depthSortWindowActors(w.get_children(), this._monitorIndex); - }); - - // The depth-sorting of cube faces is quite simple, we sort them by increasing - // rotation angle so that they are drawn back-to-front. - extensionThis._depthSortCubeFaces(this._workspaces); - }; - - - // ----------------------------------------------------------------------------------- - // --------------------- cubify workspace-switch in desktop mode --------------------- - // ----------------------------------------------------------------------------------- - - // This override rotates the workspaces during the transition to look like cube - // faces. The original movement of the workspaces is implemented in the setter of - // the progress property. We do not touch this, as keeping track of this progress - // is rather important. Instead, we listen to progress changes and tweak the - // transformation accordingly. - // This lambda is called in two places (further down), once for updates of the - // progress property, once for updates during gesture swipes. The latter does not - // trigger notify signals of the former for some reason... - const updateMonitorGroup = (group) => { - // First, we prevent any horizontal movement by countering the translation. We - // cannot simply set the x property to zero as this is used to track the - // progress. - group._container.translation_x = -group._container.x; - - // That's the desired angle between consecutive workspaces. - const faceAngle = extensionThis._getFaceAngle(group._workspaceGroups.length); - - // That's the z-distance from the cube faces to the rotation pivot. - const centerDepth = - extensionThis._getCenterDist(group._workspaceGroups[0].width, faceAngle); - - // Apply vertical rotation if required. This comes from the pitch value of the - // modified SwipeTracker created by _addDesktopDragGesture() further below. - group._container.pivot_point_z = -centerDepth; - group._container.set_pivot_point(0.5, 0.5); - group._container.rotation_angle_x = - extensionThis._pitch.value * MAX_VERTICAL_ROTATION; - - // During rotations, the cube is scaled down and the windows are "exploded". If we - // are directly facing a cube side, the strengths of both effects are approaching - // zero. The strengths of both effects are small during horizontal rotations to make - // workspace-switching not so obtrusive. However, during vertical rotations, the - // effects are stronger. - const [depthOffset, explode] = extensionThis._getExplodeFactors( - group.progress, extensionThis._pitch.value, centerDepth, group._monitor.index); - - // Rotate the individual faces. - group._workspaceGroups.forEach((child, i) => { - child.set_pivot_point_z(-centerDepth); - child.set_pivot_point(0.5, 0.5); - child.rotation_angle_y = (i - group.progress) * faceAngle; - child.translation_z = -depthOffset; - child.clip_to_allocation = false; - - // Counter the horizontal movement. - child.translation_x = -child.x; - - // Make cube transparent during vertical rotations. - child._background.opacity = 255 * (1.0 - Math.abs(extensionThis._pitch.value)); - - // Now we add some depth separation between the window clones. We get the stacking - // order from the global window list. If the explode factor becomes too small, the - // depth sorting becomes non-deterministic. - if (explode > 0.001) { - const windowActors = global.get_window_actors().filter(w => { - return child._shouldShowWindow(w.meta_window); - }); - - // Distribute the window clones translation_z values between zero and - // explode. - windowActors.forEach((windowActor, j) => { - const record = child._windowRecords.find(r => r.windowActor === windowActor); - if (record) { - record.clone.translation_z = explode * (j + 1) / windowActors.length; - } - }); - - // Now sort the window clones and the background actor according to the - // orthogonal distance of the actor planes to the camera. This ensures proper - // depth sorting. - extensionThis._depthSortWindowActors(child.get_children(), - group._monitor.index); - } - }); - - // The depth-sorting of cube faces is quite simple, we sort them by increasing - // rotation angle. - extensionThis._depthSortCubeFaces(group._workspaceGroups); - - // Update horizontal rotation of the background panorama during workspace switches. - if (this._skybox) { - this._skybox.yaw = - 2 * Math.PI * group.progress / global.workspaceManager.get_n_workspaces(); - } - }; - - // Whenever a workspace-switch is about to happen, we tweak the MonitorGroup class a - // bit to arrange the workspaces in a cube-like fashion. We have to adjust to parts of - // the code as the automatic transitions (e.g. when switching with key combinations) - // are handled differently than the gesture based switches. - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L299 - WorkspaceAnimationController.prototype._prepareWorkspaceSwitch = function() { - // Here, we call the original method without any arguments. Usually, GNOME Shell - // "skips" workspaces when switching to a workspace which is more than one workspace - // to the left or the right. This behavior is not desirable for thr cube, as it - // messes with your spatial memory. If no workspaceIndices are given to this method, - // all workspaces will be shown during the workspace switch. - extensionThis._origPrepSwitch.apply(this, []); - - // Now tweak the monitor groups. - this._switchData.monitors.forEach(m => { - // Call the method above whenever the transition progress changes. - m.connect('notify::progress', () => updateMonitorGroup(m)); - - // Call the method above whenever a gesture is active. - const orig = m.updateSwipeForMonitor; - m.updateSwipeForMonitor = function(progress, baseMonitorGroup) { - orig.apply(m, [progress, baseMonitorGroup]); - updateMonitorGroup(m); - }; - }); - - // Make sure that the background panorama is drawn above the window group during a - // workspace switch. - if (extensionThis._skybox) { - extensionThis._skybox.get_parent().remove_child(extensionThis._skybox); - Main.uiGroup.insert_child_above(extensionThis._skybox, global.window_group); - - // If the workspaces are only on the primary monitor, the skybox would cover all - // other non-rotating screens. Therefore, we temporarily limit its size to the - // primary monitor's size. - if (Meta.prefs_get_workspaces_only_on_primary()) { - const monitor = - global.display.get_monitor_geometry(global.display.get_primary_monitor()); - extensionThis._skybox.width = monitor.width; - extensionThis._skybox.height = monitor.height; - extensionThis._skybox.x = monitor.x; - extensionThis._skybox.y = monitor.y; - } - } - }; - - // Re-attach the background panorama to the stage once the workspace switch is done. - WorkspaceAnimationController.prototype._finishWorkspaceSwitch = function(...params) { - extensionThis._origFinalSwitch.apply(this, params); - - // Make sure that the skybox covers the entire stage again. - if (extensionThis._skybox) { - extensionThis._skybox.get_parent().remove_child(extensionThis._skybox); - global.stage.insert_child_below(extensionThis._skybox, null); - - if (Meta.prefs_get_workspaces_only_on_primary()) { - extensionThis._skybox.width = global.stage.width; - extensionThis._skybox.height = global.stage.height; - extensionThis._skybox.x = global.stage.x; - extensionThis._skybox.y = global.stage.y; - } - } - }; - - - // ----------------------------------------------------------------------------------- - // ------------------------- enable cube rotation by dragging ------------------------ - // ----------------------------------------------------------------------------------- - - // Usually, in GNOME Shell 40+, workspaces are move horizontally. We tweaked this to - // look like a horizontal rotation above. To store the current vertical rotation, we - // use the adjustment below. - this._pitch = new St.Adjustment({actor: global.stage, lower: -1, upper: 1}); - - // The overview's SwipeTracker will control the _overviewAdjustment of the - // WorkspacesDisplay. However, only horizontal swipes will update this adjustment. If - // only our pitch adjustment is changed (e.g. the user moved the mouse only - // vertically), the _overviewAdjustment will not change and therefore the workspaces - // will not been redrawn. Here we force redrawing by notifying changes if the pitch - // value changes. - this._pitch.connect('notify::value', () => { - if (Main.actionMode == Shell.ActionMode.OVERVIEW) { - Main.overview._overview._controls._workspacesDisplay._overviewAdjustment.notify( - 'value'); - } - }); - - // In GNOME Shell, SwipeTrackers are used all over the place to capture swipe - // gestures. There's one for entering the overview, one for switching workspaces in - // desktop mode, one for switching workspaces in overview mode, one for horizontal - // scrolling in the app drawer, and many more. The ones used for workspace-switching - // usually do not respond to single-click dragging but only to multi-touch gestures. - // We want to be able to rotate the cube with the left mouse button, so we add an - // additional gesture to these two SwipeTracker instances tracking single-click drags. - - // First, we fix an issue which leads to very quick workspace switches when the - // SwipeTracker are used with mouse clicks. When the mouse button is released, no - // event is added to the history. This means that the velocity is always calculated - // relative to the last received mouse movement. Even if he mouse pointer was - // stationary for some time, high velocities will be computed. - SwipeTracker.prototype._endGesture = function(time, distance, isTouchpad) { - // Add a final time step to the history. - this._history.append(time, 0); - - // Then call the original method. - extensionThis._origEndGesture.apply(this, [time, distance, isTouchpad]); - }; - - // Add single-click drag gesture to the desktop. - if (this._settings.get_boolean('enable-desktop-dragging')) { - this._addDesktopDragGesture(); - } - - this._settings.connect('changed::enable-desktop-dragging', () => { - if (this._settings.get_boolean('enable-desktop-dragging')) { - this._addDesktopDragGesture(); - } else { - this._removeDesktopDragGesture(); - } - }); - - // Add single-click drag gesture to the panel. - if (this._settings.get_boolean('enable-panel-dragging')) { - this._addPanelDragGesture(); - } - - this._settings.connect('changed::enable-panel-dragging', () => { - if (this._settings.get_boolean('enable-panel-dragging')) { - this._addPanelDragGesture(); - } else { - this._removePanelDragGesture(); - } - }); - - // Add single-click drag gesture to the overview. - if (this._settings.get_boolean('enable-overview-dragging')) { - this._addOverviewDragGesture(); - } - - this._settings.connect('changed::enable-overview-dragging', () => { - if (this._settings.get_boolean('enable-overview-dragging')) { - this._addOverviewDragGesture(); - } else { - this._removeOverviewDragGesture(); - } - }); - - - // ----------------------------------------------------------------------------------- - // ---------------------------------- add the skybox --------------------------------- - // ----------------------------------------------------------------------------------- - - // This is called whenever the skybox texture setting is changed. - const updateSkybox = () => { - // First, delete the existing skybox. - if (this._skybox) { - this._skybox.destroy(); - delete this._skybox; - } - - const file = this._settings.get_string('background-panorama'); - - // Then, load a new one (if any). - if (file != '') { - try { - this._skybox = new Skybox(file); - - // We add the skybox below everything. - global.stage.insert_child_below(this._skybox, null); - - // Make sure that the skybox covers the entire stage. - global.stage.bind_property('width', this._skybox, 'width', - GObject.BindingFlags.SYNC_CREATE); - global.stage.bind_property('height', this._skybox, 'height', - GObject.BindingFlags.SYNC_CREATE); - - } catch (error) { - utils.debug('Failed to set skybox: ' + error); - } - } - }; - - // Update the skybox whenever the corresponding setting is changed. - this._settings.connect('changed::background-panorama', updateSkybox); - updateSkybox(); - - // Update vertical rotation of the background panorama. - this._pitch.connect('notify::value', () => { - if (this._skybox) { - this._skybox.pitch = (this._pitch.value * MAX_VERTICAL_ROTATION) * Math.PI / 180; - } - }); - - // Update horizontal rotation of the background panorama during workspace switches in - // the overview. - Main.overview._overview.controls._workspaceAdjustment.connect('notify::value', () => { - if (this._skybox) { - this._skybox.yaw = 2 * Math.PI * - Main.overview._overview.controls._workspaceAdjustment.value / - global.workspaceManager.get_n_workspaces(); - } - }); - - - // ----------------------------------------------------------------------------------- - // ----------------------- enable edge-drag workspace-switches ----------------------- - // ----------------------------------------------------------------------------------- - - // We add two Meta.Barriers, one at each side of the stage. If the pointer hits one of - // these with enough pressure while dragging a window, we initiate a workspace-switch. - // The last parameter (0) is actually supposed to be a bitwise combination of - // Shell.ActionModes. The pressure barrier will only trigger, if Main.actionMode - // equals one of the given action modes. This works well for Shell.ActionMode.NORMAL - // and Shell.ActionMode.OVERVIEW, however it does not work for Shell.ActionMode.NONE - // (which actually equals zero). However, when we want the barriers to also trigger in - // Shell.ActionMode.NONE, as this is the mode during a drag-operation in the overview. - // Therefore, we modify the _onBarrierHit method of the pressure barrier to completely - // ignore this parameter. Instead, we check for the correct action mode in the trigger - // handler. - this._pressureBarrier = - new PressureBarrier(this._settings.get_int('edge-switch-pressure'), 1000, 0); - - // Update pressure threshold when the corresponding settings key changes. - this._settings.connect('changed::edge-switch-pressure', () => { - this._pressureBarrier._threshold = this._settings.get_int('edge-switch-pressure'); - }); - - // This is an exact copy of the original _onBarrierHit, with only one line disabled to - // ignore the given ActionMode. - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/layout.js#L1366 - this._pressureBarrier._onBarrierHit = function(barrier, event) { - barrier._isHit = true; - - // If we've triggered the barrier, wait until the pointer has the - // left the barrier hitbox until we trigger it again. - if (this._isTriggered) return; - - if (this._eventFilter && this._eventFilter(event)) return; - - // Throw out all events not in the proper keybinding mode - // if (!(this._actionMode & Main.actionMode)) return; - - let slide = this._getDistanceAlongBarrier(barrier, event); - let distance = this._getDistanceAcrossBarrier(barrier, event); - - if (distance >= this._threshold) { - this._trigger(); - return; - } - - // Throw out events where the cursor is move more - // along the axis of the barrier than moving with - // the barrier. - if (slide > distance) return; - - this._lastTime = event.time; - - this._trimBarrierEvents(); - distance = Math.min(15, distance); - - this._barrierEvents.push([event.time, distance]); - this._currentPressure += distance; - - if (this._currentPressure >= this._threshold) this._trigger(); - }; - - // Now we add the left and right barrier to the pressure barrier. - const createBarriers = () => { - if (this._leftBarrier) { - this._pressureBarrier.removeBarrier(this._leftBarrier); - this._leftBarrier.destroy(); - } - - if (this._rightBarrier) { - this._pressureBarrier.removeBarrier(this._rightBarrier); - this._rightBarrier.destroy(); - } - - // Since GNOME 46, the display property is not required anymore. - if (GS_VERSION <= 45) { - this._leftBarrier = new Meta.Barrier({ - display: global.display, - x1: 0, - x2: 0, - y1: 1, - y2: global.stage.height, - directions: Meta.BarrierDirection.POSITIVE_X, - }); - - this._rightBarrier = new Meta.Barrier({ - display: global.display, - x1: global.stage.width, - x2: global.stage.width, - y1: 1, - y2: global.stage.height, - directions: Meta.BarrierDirection.NEGATIVE_X, - }); - } else { - this._leftBarrier = new Meta.Barrier({ - x1: 0, - x2: 0, - y1: 1, - y2: global.stage.height, - directions: Meta.BarrierDirection.POSITIVE_X, - }); - - this._rightBarrier = new Meta.Barrier({ - x1: global.stage.width, - x2: global.stage.width, - y1: 1, - y2: global.stage.height, - directions: Meta.BarrierDirection.NEGATIVE_X, - }); - } - - this._pressureBarrier.addBarrier(this._leftBarrier); - this._pressureBarrier.addBarrier(this._rightBarrier); - }; - - // Re-create the barriers whenever the stage's allocation is changed. - this._stageAllocationID = global.stage.connect('notify::allocation', createBarriers); - createBarriers(); - - // When the pressure barrier is triggered, the corresponding setting is enabled, and a - // window is currently dragged, we move the dragged window to the adjacent workspace - // and activate it as well. - this._pressureBarrier.connect('trigger', () => { - const direction = - this._leftBarrier._isHit ? Meta.MotionDirection.LEFT : Meta.MotionDirection.RIGHT; - - const newWorkspace = - global.workspace_manager.get_active_workspace().get_neighbor(direction); - - if (Main.actionMode == Shell.ActionMode.NORMAL && this._draggedWindow && - this._settings.get_boolean('enable-desktop-edge-switch')) { - Main.wm.actionMoveWindow(this._draggedWindow, newWorkspace); - } else if (Main.actionMode == Shell.ActionMode.NONE && Main.overview.visible && - this._settings.get_boolean('enable-overview-edge-switch')) { - newWorkspace.activate(global.get_current_time()); - } - }); - - // Keep a reference to the currently dragged window. - global.display.connect('grab-op-begin', (d, win, op) => { - if (op == Meta.GrabOp.MOVING) { - this._draggedWindow = win; - } - }); - - // Release the reference to the currently dragged window. - global.display.connect('grab-op-end', (d, win, op) => { - if (op == Meta.GrabOp.MOVING) { - this._draggedWindow = null; - } - }); - - - // ----------------------------------------------------------------------------------- - // ------------------- fix perspective of multi-monitor setups ----------------------- - // ----------------------------------------------------------------------------------- - - // Usually, GNOME Shell uses one central perspective for all monitors combined. This - // results in a somewhat sheared appearance of the cube on multi-monitor setups where - // the primary monitor is not in the middle (or cubes are shown on multiple monitors). - // With the code below, we modify the projection and view matrices for each monitor so - // that each monitor uses its own central perspective. This seems to be possible on - // Wayland only. On X11, there's only one set of projection and view matrices for all - // monitors combined, so we tweak them so that the projection center is in the middle - // of the primary monitor. So it will at least only look bad on X11 if the cube is - // shown on all monitors... - const updateMonitorPerspective = () => { - // Disable the perspective fixes first... - this._disablePerspectiveCorrection(); - - // Store this so we do not have to get it too often. - this._enablePerMonitorPerspective = - this._settings.get_boolean('per-monitor-perspective') && - global.display.get_n_monitors() > 1; - - // ... and then enable them if required. - if (this._enablePerMonitorPerspective) { - this._enablePerspectiveCorrection(); - } - }; - - this._settings.connect('changed::per-monitor-perspective', updateMonitorPerspective); - this._monitorsChangedID = global.backend.get_monitor_manager().connect( - 'monitors-changed', updateMonitorPerspective); - - updateMonitorPerspective(); - } - - // This function could be called after the extension is uninstalled, disabled in GNOME - // Tweaks, when you log out or when the screen locks. - disable() { - - // Restore the original behavior. - SwipeTracker.prototype._endGesture = this._origEndGesture; - WorkspacesView.prototype._updateWorkspacesState = this._origUpdateWorkspacesState; - WorkspacesView.prototype._getSpacing = this._origGetSpacing; - WorkspacesView.prototype._updateVisibility = this._origUpdateVisibility; - WorkspaceAnimationController.prototype._prepareWorkspaceSwitch = this._origPrepSwitch; - WorkspaceAnimationController.prototype._finishWorkspaceSwitch = this._origFinalSwitch; - - // Remove all drag-to-rotate gestures. - this._removeDesktopDragGesture(); - this._removePanelDragGesture(); - this._removeOverviewDragGesture(); - - // Clean up skybox. - if (this._skybox) { - this._skybox.destroy(); - this._skybox = null; - } - - // Clean up the edge-workspace-switching. - global.stage.disconnect(this._stageAllocationID); - - this._pressureBarrier.destroy(); - this._leftBarrier.destroy(); - this._rightBarrier.destroy(); - - this._pressureBarrier = null; - this._leftBarrier = null; - this._rightBarrier = null; - - // Clean up perspective correction. - this._disablePerspectiveCorrection(); - global.backend.get_monitor_manager().disconnect(this._monitorsChangedID); - - // Make sure that the settings object is freed. - this._settings = null; - } - - // ----------------------------------------------------------------------- private stuff - - // Calls inhibit_culling on the given actor and recursively on all mapped children. - _inhibitCulling(actor) { - if (actor.mapped) { - actor.inhibit_culling(); - actor._culling_inhibited_by_desktop_cube = true; - actor.get_children().forEach(c => this._inhibitCulling(c)); - } - }; - - // Calls uninhibit_culling on the given actor and recursively on all children. It will - // only call uninhibit_culling() on those actors which were inhibited before. - _uninhibitCulling(actor) { - if (actor._culling_inhibited_by_desktop_cube) { - delete actor._culling_inhibited_by_desktop_cube; - actor.uninhibit_culling(); - actor.get_children().forEach(c => this._uninhibitCulling(c)); - } - }; - - // Returns a value between [0...1] blending between overview (0) and app grid mode (1). - _getAppDrawerMode(workspacesView) { - return workspacesView._fitModeAdjustment.value; - } - - // Returns a value between [0...1] blending between desktop / app drawer mode (0) and - // overview mode (1). - _getOverviewMode(workspacesView) { - return workspacesView._overviewAdjustment.value - - 2 * this._getAppDrawerMode(workspacesView); - } - - // Returns a value between [0...1]. If it's 0, the cube should be unfolded, if it's 1, - // the cube should be drawn like, well, a cube :). - _getCubeMode(workspacesView) { - return 1 - this._getAppDrawerMode(workspacesView) - } - - // Returns the angle between consecutive workspaces. - _getFaceAngle(faceCount) { - - // With this setting, our "cube" only covers 180°, if there are only two workspaces, - // it covers 90°. This prevents the affordance that it could be possible to switch - // from the last ot the first workspace. - if (this._settings.get_boolean('last-first-gap')) { - return (faceCount == 2 ? 90 : 180) / (faceCount - 1); - } - - // Else the "cube" covers 360°. - return 360.0 / faceCount; - } - - // Returns the z-distance from the cube faces to the rotation pivot. - _getCenterDist(workspaceWidth, faceAngle) { - let centerDepth = workspaceWidth / 2; - if (faceAngle < 180) { - centerDepth /= Math.tan(faceAngle * 0.5 * Math.PI / 180); - } - return centerDepth; - } - - // This sorts the given list of children actors (which are supposed to be attached to - // the same parent) by increasing absolute rotation-y angle. This is used for - // depth-sorting, as cube faces which are less rotated, are in front of others. - _depthSortCubeFaces(actors) { - // First create a copy of the actors list and sort it by decreasing rotation angle. - const copy = actors.slice(); - copy.sort((a, b) => { - return Math.abs(b.rotation_angle_y) - Math.abs(a.rotation_angle_y); - }); - - // Then sort the children actors accordingly. - const parent = actors[0].get_parent(); - for (let i = 0; i < copy.length; i++) { - parent.set_child_at_index(copy[i], -1); - } - } - - // This sorts the given list of children actors (which are supposed to be attached to - // the same parent) by increasing orthogonal distance to the camera. To do this, the - // camera position is projected onto the plane defined by the actor and the absolute - // distance from the camera to its projected position is computed. This is used for - // depth-sorting a list of parallel actors. - _depthSortWindowActors(actors, monitorIndex) { - - // Sanity check. - if (actors.length <= 1) { - return; - } - - // First, compute distance of virtual camera to the front workspace plane. - const camera = new Graphene.Point3D({ - x: global.stage.width / 2, - y: global.stage.height / 2, - z: global.stage.height / - (2 * Math.tan(global.stage.perspective.fovy / 2 * Math.PI / 180)) - }); - - // All actors are expected to share the same parent. - const parent = actors[0].get_parent(); - - // If the perspective is corrected for multi-monitor setups, the virtual camera is not - // in the middle of the stage but rather in front of each monitor. - if (this._enablePerMonitorPerspective) { - - let monitor; - - if (Meta.is_wayland_compositor()) { - - // On Wayland, each monitor should have its own StageView. Therefore, the virtual - // camera has been positioned in front of each monitor separately. - monitor = global.display.get_monitor_geometry(monitorIndex); - - } else { - - // On X11, there's only one StageView. We move the virtual camera so that it is in - // front of the primary monitor. - monitor = - global.display.get_monitor_geometry(global.display.get_primary_monitor()); - } - - camera.x = monitor.x + monitor.width / 2; - camera.y = monitor.y + monitor.height / 2; - } - - // Create a list of the orthogonal distances to the camera for each actor. - const distances = actors.map((a, i) => { - // A point on the actor plane. - const onActor = a.apply_relative_transform_to_point( - null, new Graphene.Point3D({x: 0, y: 0, z: 0})); - - // A point one unit above the actor plane. - const aboveActor = a.apply_relative_transform_to_point( - null, new Graphene.Point3D({x: 0, y: 0, z: 1000})); - - // The normal vector on the actor plane. - const normal = new Graphene.Point3D({ - x: aboveActor.x - onActor.x, - y: aboveActor.y - onActor.y, - z: aboveActor.z - onActor.z, - }); - - const length = - Math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z); - normal.x /= length; - normal.y /= length; - normal.z /= length; - - onActor.x -= camera.x; - onActor.y -= camera.y; - onActor.z -= camera.z; - - // Return the length of the projected vector. - return { - index: i, - distance: onActor.x * normal.x + onActor.y * normal.y + onActor.z * normal.z - }; - }); - - // Sort by decreasing distance. - distances.sort((a, b) => { - return Math.abs(b.distance) - Math.abs(a.distance); - }); - - // Then use this to create a sorted list of actors. - const copy = distances.map(e => { - return actors[e.index]; - }); - - // Finally, sort the children actors accordingly. - for (let i = 0; i < copy.length; i++) { - parent.set_child_at_index(copy[i], -1); - } - } - - // During rotations, the cube is scaled down and the windows are "exploded". If we - // are directly facing a cube side, the strengths of both effects are approaching - // zero. The strengths of both effects are small during horizontal rotations to make - // workspace-switching not so obtrusive. However, during vertical rotations, the - // effects are stronger. - // This method returns two values: - // result[0]: A translation value by which the cube should be moved backwards. - // result[1]: A translation value by which windows may be moved away from the cube. - _getExplodeFactors(hRotation, vRotation, centerDepth, monitorIndex) { - - // These are zero if we are facing a workspace and one if we look directly at an - // edge between adjacent workspaces or if the cube is rotated vertically - // respectively. - const hFactor = 1.0 - 2.0 * Math.abs(hRotation % 1 - 0.5); - const vFactor = Math.abs(vRotation); - - // For horizontal rotations, we want to scale the cube (or rather move it backwards) - // a tiny bit to reveal a bit of parallax. However, if we have many cube sides, this - // looks weird, so we reduce the effect there. We use the offset which would make - // the cube's corners stay behind the original workspace faces during he rotation. - const monitor = global.display.get_monitor_geometry(monitorIndex); - const cornerDist = - Math.sqrt(Math.pow(centerDepth, 2) + Math.pow(monitor.width / 2, 2)); - const hDepthOffset = - this._settings.get_double('window-parallax') * (cornerDist - centerDepth); - - // The explode factor is set to the hDepthOffset value to make the front-most - // window stay at a constant depth. - const hExplode = hDepthOffset; - - // For vertical rotations, we move the cube backwards to reveal everything. The - // maximum explode width is set to half of the workspace size. - const vExplode = this._settings.get_boolean('do-explode') ? - Math.max(monitor.width, monitor.height) / 2 : - 0; - const diameter = 2 * (vExplode + centerDepth); - const camDist = - monitor.height / (2 * Math.tan(global.stage.perspective.fovy / 2 * Math.PI / 180)); - const vDepthOffset = - (1 + PADDING_V_ROTATION) * diameter * camDist / monitor.width - centerDepth; - - // Use current maximum of both values. - const depthOffset = Math.max(hFactor * hDepthOffset, vFactor * vDepthOffset); - const explode = Math.max(hFactor * hExplode, vFactor * vExplode); - - // Do not explode the cube in app drawer state. The stateAdjustment is... - // ... 0 on the desktop - // ... 1 in the window picker - // ... 2 in the app drawer - const windowPickerFactor = - Math.min(1.0, 2.0 - Main.overview._overview.controls._stateAdjustment.value); - - return [depthOffset * windowPickerFactor, explode * windowPickerFactor]; - } - - // Usually, GNOME Shell uses one central perspective for all monitors combined. This - // results in a somewhat sheared appearance of the cube on multi-monitor setups where - // the primary monitor is not in the middle (or cubes are shown on multiple monitors). - // With the code below, we modify the projection and view matrices for each monitor so - // that each monitor uses its own central perspective. This seems to be possible on - // Wayland only. On X11, there's only one set of projection and view matrices for all - // monitors combined, so we tweak them so that the projection center is in the middle of - // the primary monitor. So it will at least only look bad on X11 if the cube is shown on - // all monitors... - _enablePerspectiveCorrection() { - - this._stageBeforeUpdateID = global.stage.connect('before-update', (stage, view) => { - // Do nothing if neither overview or desktop switcher are shown. - if (!Main.overview.visible && Main.wm._workspaceAnimation._switchData == null) { - return; - } - - // Usually, the virtual camera is positioned centered in front of the stage. We will - // move the virtual camera around. These variables will be the new stage-relative - // coordinates of the virtual camera. - let cameraX, cameraY; - - if (Meta.is_wayland_compositor()) { - - // On Wayland, each monitor has its own StageView. Therefore we can move the - // virtual camera for each monitor separately. - cameraX = view.layout.x + view.layout.width / 2; - cameraY = view.layout.y + view.layout.height / 2; - - } else { - - // On X11, there's only one StageView. We move the virtual camera so that it is in - // front of the current monitor. - const currentMonitorRect = - global.display.get_monitor_geometry(global.display.get_current_monitor()); - - cameraX = currentMonitorRect.x + currentMonitorRect.width / 2; - cameraY = currentMonitorRect.y + currentMonitorRect.height / 2; - } - - // This is the offset to the original, centered camera position. Y is flipped due to - // some negative scaling at some point in Mutter. - const camOffsetX = stage.width / 2 - cameraX; - const camOffsetY = cameraY - stage.height / 2; - - const z_near = stage.perspective.z_near; - const z_far = stage.perspective.z_far; - - // The code below is copied from Mutter's Clutter. - // https://gitlab.gnome.org/GNOME/mutter/-/blob/main/clutter/clutter/clutter-stage.c#L2255 - const A = 0.57735025882720947265625; - const B = 0.866025388240814208984375; - const C = 0.86162912845611572265625; - const D = 0.00872653536498546600341796875; - - const z_2d = z_near * A * B * C / D + z_near; - - // The code below is copied from Mutter's Clutter as well. - // https://gitlab.gnome.org/GNOME/mutter/-/blob/main/clutter/clutter/clutter-stage.c#L2270 - const top = z_near * Math.tan(stage.perspective.fovy * Math.PI / 360.0); - const left = -top * stage.perspective.aspect; - const right = top * stage.perspective.aspect; - const bottom = -top; - - const left_2d_plane = left / z_near * z_2d; - const right_2d_plane = right / z_near * z_2d; - const bottom_2d_plane = bottom / z_near * z_2d; - const top_2d_plane = top / z_near * z_2d; - - const width_2d_start = right_2d_plane - left_2d_plane; - const height_2d_start = top_2d_plane - bottom_2d_plane; - - const width_scale = width_2d_start / stage.width; - const height_scale = height_2d_start / stage.height; - // End of the copy-paste code. - - // Compute the required offset of the frustum planes at the near plane. This - // basically updates the projection matrix according to our new camera position. - const offsetX = camOffsetX * width_scale / z_2d * z_near; - const offsetY = camOffsetY * height_scale / z_2d * z_near; - - // Set the new frustum. - view.get_framebuffer().frustum(left + offsetX, right + offsetX, bottom + offsetY, - top + offsetY, z_near, z_far); - - // Translate the virtual camera. This basically updates the view matrix according to - // our new camera position. - view.get_framebuffer().push_matrix(); - view.get_framebuffer().translate(camOffsetX * width_scale, - camOffsetY * height_scale, 0); - - // If the perspective of each monitor is computed separately, the culling of GNOME - // Shell does not work anymore as it still uses the original frustum. The only - // workaround is to disable culling altogether. This will be bad performance-wise, - // but I do not see an alternative. - // If the overview is shown, we inhibit culling for the WorkspacesDisplay. If the - // desktop-workspace-switcher is shown, we inhibit culling for all shown monitor - // groups. - if (Main.overview.visible) { - this._inhibitCulling(Main.overview._overview.controls._workspacesDisplay); - } else if (Main.wm._workspaceAnimation._switchData) { - Main.wm._workspaceAnimation._switchData.monitors.forEach(m => { - this._inhibitCulling(m); - }); - } - }); - - // Revert the matrix changes before the update, - this._stageAfterUpdateID = global.stage.connect('after-update', (stage, view) => { - // Nothing to do if neither overview or desktop switcher are shown. - if (!Main.overview.visible && Main.wm._workspaceAnimation._switchData == null) { - return; - } - - view.get_framebuffer().pop_matrix(); - view.get_framebuffer().perspective(stage.perspective.fovy, stage.perspective.aspect, - stage.perspective.z_near, - stage.perspective.z_far); - - // Re-enable culling for all relevant actors. - if (Main.overview.visible) { - this._uninhibitCulling(Main.overview._overview.controls._workspacesDisplay); - } else if (Main.wm._workspaceAnimation._switchData) { - Main.wm._workspaceAnimation._switchData.monitors.forEach(m => { - this._uninhibitCulling(m); - }); - } - }); - } - - // Reverts the changes done with the method above. - _disablePerspectiveCorrection() { - - if (this._stageBeforeUpdateID) { - global.stage.disconnect(this._stageBeforeUpdateID); - this._stageBeforeUpdateID = 0; - } - - if (this._stageAfterUpdateID) { - global.stage.disconnect(this._stageAfterUpdateID); - this._stageAfterUpdateID = 0; - } - } - - // This creates a custom drag gesture and adds it to the given SwipeTracker. The swipe - // tracker will now also respond to horizontal drags. The additional gesture also - // reports vertical drag movements via the "pitch" property. This method returns an - // object containing the gesture, an St.Adjustment which will contain this pitch value, - // and a connection ID which is used by _removeDragGesture() to clean up. When the - // SwipeTracker's gesture ends, the St.Adjustment's value will be eased to zero. - _addDragGesture(actor, tracker, mode) { - const gesture = new DragGesture(actor, mode); - gesture.connect('begin', tracker._beginGesture.bind(tracker)); - gesture.connect('update', tracker._updateGesture.bind(tracker)); - gesture.connect('end', tracker._endTouchGesture.bind(tracker)); - tracker.bind_property('distance', gesture, 'distance', - GObject.BindingFlags.SYNC_CREATE); - - // Update the gesture's sensitivity when the corresponding settings value changes. - this._settings.bind('mouse-rotation-speed', gesture, 'sensitivity', - Gio.SettingsBindFlags.GET); - - // Connect the gesture's pitch property to the pitch adjustment. - gesture.bind_property('pitch', this._pitch, 'value', 0); - - // Ease the pitch adjustment to zero if the SwipeTracker reports an ended gesture. - // This ensures that the cube smoothly rotates back when released. The end-signal - // returns a suitable duration for this, however this depends on the horizontal - // rotation required to move the cube back. Here, we compute a duration required for - // the vertical rotation and use the maximum of both values for the final easing. - const gestureEndID = tracker.connect('end', (g, duration) => { - this._pitch.remove_transition('value'); - this._pitch.ease(0, { - duration: Math.max(500 * Math.abs(this._pitch.value), duration), - mode: Clutter.AnimationMode.EASE_OUT_CUBIC, - }); - }); - - // We return all things which are required to remove the gesture again. This can be - // done with the _removeDragGesture() method below. - return { - actor: actor, - tracker: tracker, - gesture: gesture, - trackerConnection: gestureEndID - }; - } - - // Removes a single-click drag gesture created earlier via _addDragGesture(). The info - // parameter should be the object returned by _addDragGesture(). - _removeDragGesture(info) { - info.gesture.destroy(); - info.tracker.disconnect(info.trackerConnection); - } - - // Calls _addDragGesture() for the SwipeTracker and actor responsible for - // workspace-switching in desktop mode when dragging on the background. - _addDesktopDragGesture() { - // The SwipeTracker for switching workspaces in desktop mode is created here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L285 - const tracker = Main.wm._workspaceAnimation._swipeTracker; - let actor = Main.layoutManager._backgroundGroup; - const mode = Shell.ActionMode.NORMAL; - - // If not in the overview, you can usually only swipe to adjacent workspaces. This - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/swipeTracker.js#L633 - // allows us to override this behavior. - tracker.allowLongSwipes = true; - - // We have to make the background reactive. Make sure to store the current state so - // that we can reset it later. - this._origBackgroundReactivity = actor.reactive; - actor.reactive = true; - - this._desktopDragGesture = this._addDragGesture(actor, tracker, mode); - } - - // Calls _addDragGesture() for the SwipeTracker and actor responsible for - // workspace-switching in desktop mode when dragging on the panel. - _addPanelDragGesture() { - // The SwipeTracker for switching workspaces in desktop mode is created here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspaceAnimation.js#L285 - const tracker = Main.wm._workspaceAnimation._swipeTracker; - const actor = Main.panel; - const mode = Shell.ActionMode.NORMAL; - - // If not in the overview, you can usually only swipe to adjacent workspaces. This - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/swipeTracker.js#L633 - // allows us to override this behavior. - tracker.allowLongSwipes = true; - - // We have to prevent moving fullscreen windows when dragging. - this._origPanelTryDragWindow = actor._tryDragWindow; - actor._tryDragWindow = () => Clutter.EVENT_PROPAGATE; - - this._panelDragGesture = this._addDragGesture(actor, tracker, mode); - } - - // Calls _addDragGesture() for the SwipeTracker and actor responsible for - // workspace-switching in overview mode. - _addOverviewDragGesture() { - // The SwipeTracker for switching workspaces in overview mode is created here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/workspacesView.js#L827 - const tracker = Main.overview._overview._controls._workspacesDisplay._swipeTracker; - const actor = Main.layoutManager.overviewGroup; - const mode = Shell.ActionMode.OVERVIEW; - - this._overviewDragGesture = this._addDragGesture(actor, tracker, mode); - } - - // Calls _removeDragGesture() for the SwipeTracker and actor responsible for - // workspace-switching in desktop mode when dragging on the background. - _removeDesktopDragGesture() { - if (this._desktopDragGesture) { - - // Restore original behavior. - this._desktopDragGesture.tracker.allowLongSwipes = false; - - // Make sure to restore the original state. - this._desktopDragGesture.actor.reactive = this._origBackgroundReactivity; - - this._removeDragGesture(this._desktopDragGesture); - - delete this._desktopDragGesture; - } - } - - // Calls _removeDragGesture() for the SwipeTracker and actor responsible for - // workspace-switching in desktop mode when dragging on the panel. - _removePanelDragGesture() { - if (this._panelDragGesture) { - - // Restore original behavior. - this._panelDragGesture.tracker.allowLongSwipes = false; - - // Make sure to restore the original state. - this._panelDragGesture.actor._tryDragWindow = this._origPanelTryDragWindow; - - this._removeDragGesture(this._panelDragGesture); - - delete this._panelDragGesture; - } - } - - // Calls _removeDragGesture() for the SwipeTracker and actor responsible for - // workspace-switching in overview mode. - _removeOverviewDragGesture() { - if (this._overviewDragGesture) { - this._removeDragGesture(this._overviewDragGesture); - - delete this._overviewDragGesture; - } - } -} - -// This function is called once when the extension is loaded, not enabled. -function init() { - return new Extension(); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ar/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ar/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index b6a78a83..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ar/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ca/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ca/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 705429b5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ca/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/cs/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/cs/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 2664a4b2..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/cs/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/de/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/de/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index c5754622..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/de/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/eo/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/eo/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 50b6307a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/eo/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/es/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/es/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 93a900ad..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/es/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/fi/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/fi/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index a01bc39c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/fi/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/fr/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/fr/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 85e6c155..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/fr/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/gl/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/gl/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 85b66987..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/gl/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/hi/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/hi/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 887f343d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/hi/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/it/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/it/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 278d1682..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/it/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ja/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ja/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 68870428..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ja/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/lt/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/lt/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index ecc88ab7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/lt/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/nb_NO/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/nb_NO/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 6065729b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/nb_NO/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/nl/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/nl/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 85bd0f94..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/nl/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/pl/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/pl/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 96cc31c7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/pl/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ru/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ru/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 1a3013ba..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/ru/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sk/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sk/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 8709a1ea..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sk/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sl/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sl/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 3d2c8fc8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sl/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sv/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sv/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 725a96f8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/sv/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/tr/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/tr/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index 4da2c842..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/tr/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/zh_Hans/LC_MESSAGES/desktop-cube.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/zh_Hans/LC_MESSAGES/desktop-cube.mo deleted file mode 100755 index dc5293b0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/locale/zh_Hans/LC_MESSAGES/desktop-cube.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/metadata.json deleted file mode 100755 index d4ae55f4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/metadata.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Indulge in nostalgia with useless 3D effects.", - "donations": { - "github": "schneegans", - "kofi": "schneegans", - "paypal": "simonschneegans" - }, - "gettext-domain": "desktop-cube", - "name": "Desktop Cube", - "settings-schema": "org.gnome.shell.extensions.desktop-cube", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/Schneegans/Desktop-Cube", - "uuid": "desktop-cube@schneegans.github.com", - "version": 24 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/prefs.js deleted file mode 100755 index b8daf8fb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/prefs.js +++ /dev/null @@ -1,207 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // -// | \ | ( ` | / | / \ | ) / | | | ) | // -// | | |- `-. |< | | | |-' | | | |-< |- // -// | / | . ) | \ | \ / | \ | | | ) | // -// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // -////////////////////////////////////////////////////////////////////////////////////////// - -// SPDX-FileCopyrightText: Simon Schneegans -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; -import Gdk from 'gi://Gdk'; -import Adw from 'gi://Adw'; - -import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; -import {registerImageChooserButton} from './src/ImageChooserButton.js'; - -////////////////////////////////////////////////////////////////////////////////////////// -// For now, the preferences dialog of this extension is very simple. In the future, if // -// we might consider to improve its layout... // -////////////////////////////////////////////////////////////////////////////////////////// - -export default class DesktopCubePreferences extends ExtensionPreferences { - - // -------------------------------------------------------------------- public interface - - // This function is called when the preferences window is created. We create a new - // instance of the PreferencesDialog class each time this method is called. This way we - // can actually open multiple settings windows and interact with all of them properly. - fillPreferencesWindow(window) { - // Load all of our resources. - this._resources = Gio.Resource.load(this.path + '/resources/desktop-cube.gresource'); - Gio.resources_register(this._resources); - - // Register our custom widgets. - registerImageChooserButton(); - - // Load the user interface file. - this._builder = new Gtk.Builder(); - this._builder.add_from_resource(`/ui/settings.ui`); - - // Make sure custom icons are found. - Gtk.IconTheme.get_for_display(Gdk.Display.get_default()).add_resource_path('/img'); - - // These are our top-level preferences pages which we will return later. - this._pages = [ - this._builder.get_object('general-page'), this._builder.get_object('desktop-page'), - this._builder.get_object('overview-page') - ]; - - // Store a reference to the settings object. - this._settings = this.getSettings(); - - // Bind all properties. - this._bindAdjustment('workpace-separation'); - this._bindAdjustment('horizontal-stretch'); - this._bindAdjustment('window-parallax'); - this._bindImageChooserButton('background-panorama'); - this._bindSwitch('last-first-gap'); - this._bindSwitch('enable-desktop-dragging'); - this._bindSwitch('enable-panel-dragging'); - this._bindSwitch('enable-desktop-edge-switch'); - this._bindSwitch('enable-overview-edge-switch'); - this._bindSwitch('enable-overview-dragging'); - this._bindSwitch('do-explode'); - this._bindSwitch('per-monitor-perspective'); - this._bindAdjustment('active-workpace-opacity'); - this._bindAdjustment('inactive-workpace-opacity'); - this._bindAdjustment('edge-switch-pressure'); - this._bindAdjustment('mouse-rotation-speed'); - - // Inject the video link. - const label = this._builder.get_object('central-perspective-row'); - label.subtitle = label.subtitle.replace( - '%s', 'https://youtu.be/dpYyn1BXGjU'); - - // Add a menu to the title bar of the preferences dialog. - this._pages[0].connect('realize', (widget) => { - const window = widget.get_root(); - - // Add the menu to the header bar. - const menu = this._builder.get_object('menu-button'); - const header = this._findWidgetByType(window.get_content(), Adw.HeaderBar); - header.pack_start(menu); - - // Populate the actions. - const group = Gio.SimpleActionGroup.new(); - - const addAction = (name, uri) => { - const action = Gio.SimpleAction.new(name, null); - action.connect('activate', () => Gtk.show_uri(null, uri, Gdk.CURRENT_TIME)); - group.add_action(action); - }; - - // clang-format off - addAction('homepage', 'https://github.com/Schneegans/Desktop-Cube'); - addAction('changelog', 'https://github.com/Schneegans/Desktop-Cube/blob/main/docs/changelog.md'); - addAction('translate', 'https://hosted.weblate.org/engage/desktop-cube/'); - addAction('bugs', 'https://github.com/Schneegans/Desktop-Cube/issues'); - addAction('donate-kofi', 'https://ko-fi.com/schneegans'); - addAction('donate-github', 'https://github.com/sponsors/Schneegans'); - addAction('donate-paypal', 'https://www.paypal.me/simonschneegans'); - addAction('show-sponsors', 'https://schneegans.github.io/sponsors'); - // clang-format on - - // Add the about dialog. - const aboutAction = Gio.SimpleAction.new('about', null); - aboutAction.connect('activate', () => { - // The JSON report format from weblate is a bit weird. Here we extract all - // unique names from the translation report. - const translators = new Set(); - this._getJSONResource('/credits/translators.json').forEach(i => { - for (const j of Object.values(i)) { - j.forEach(k => translators.add(k[1])); - } - }); - - const dialog = new Adw.AboutWindow({transient_for: window, modal: true}); - dialog.set_application_icon('desktop-cube-symbolic'); - dialog.set_application_name('Desktop Cube'); - dialog.set_version(`${this.metadata.version}`); - dialog.set_developer_name('Simon Schneegans'); - dialog.set_issue_url('https://github.com/Schneegans/Desktop-Cube/issues'); - dialog.set_translator_credits([...translators].join('\n')); - dialog.set_copyright('© 2023 Simon Schneegans'); - dialog.set_website('https://github.com/Schneegans/Desktop-Cube'); - dialog.set_license_type(Gtk.License.GPL_3_0); - - dialog.show(); - }); - group.add_action(aboutAction); - - window.insert_action_group('prefs', group); - }); - - window.set_search_enabled(true); - - this._pages.forEach(page => { - window.add(page); - }); - - // As we do not have something like a destructor, we just listen for the destroy - // signal of our general page. - this._pages[0].connect('destroy', () => { - // Unregister our resources. - Gio.resources_unregister(this._resources); - }); - } - - - // ----------------------------------------------------------------------- private stuff - - // Connects a DesktopCubeImageChooserButton (or anything else which has a 'file' - // property) to a settings key. It also binds the corresponding reset button. - _bindImageChooserButton(settingsKey) { - this._bind(settingsKey, 'file'); - } - - // Connects a Gtk.Adjustment (or anything else which has a 'value' property) to a - // settings key. It also binds the corresponding reset button. - _bindAdjustment(settingsKey) { - this._bind(settingsKey, 'value'); - } - - // Connects a Gtk.Switch (or anything else which has an 'active' property) to a settings - // key. It also binds the corresponding reset button. - _bindSwitch(settingsKey) { - this._bind(settingsKey, 'active'); - } - - // Connects any widget's property to a settings key. The widget must have the same ID as - // the settings key. It also binds the corresponding reset button. - _bind(settingsKey, property) { - this._settings.bind(settingsKey, this._builder.get_object(settingsKey), property, - Gio.SettingsBindFlags.DEFAULT); - - const resetButton = this._builder.get_object('reset-' + settingsKey); - resetButton.connect('clicked', () => { - this._settings.reset(settingsKey); - }); - } - - // Reads the contents of a JSON file contained in the global resources archive. The data - // is parsed and returned as a JavaScript object / array. - _getJSONResource(path) { - const data = Gio.resources_lookup_data(path, 0); - const string = new TextDecoder().decode(data.get_data()); - return JSON.parse(string); - } - - // This traverses the widget tree below the given parent recursively and returns the - // first widget of the given type. - _findWidgetByType(parent, type) { - for (const child of [...parent]) { - if (child instanceof type) return child; - - const match = this._findWidgetByType(child, type); - if (match) return match; - } - - return null; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/resources/desktop-cube.gresource b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/resources/desktop-cube.gresource deleted file mode 100755 index 0fe04f65..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/resources/desktop-cube.gresource and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/schemas/gschemas.compiled deleted file mode 100755 index f1677ad4..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/schemas/org.gnome.shell.extensions.desktop-cube.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/schemas/org.gnome.shell.extensions.desktop-cube.gschema.xml deleted file mode 100755 index 8b68f3ab..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/schemas/org.gnome.shell.extensions.desktop-cube.gschema.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - 0.5 - Window Parallax - The strength of the parallax effect of windows. - - - - true - Last First Gap - Add a gap between last and first workspace. - - - - true - Do Explode - Explode the cube on vertical rotations. - - - - true - Per Monitor Perspective - Tweak the projection matrices for better multi-monitor support. - - - - "" - Background Panorama - The texture used for the skybox. - - - - 200 - Edge Switch Pressure - The amount of pressure required to switch workspaces when dragging a window. - - - - 2.0 - Mouse Rotation Speed - A multiplier for the desktop cube rotation when dragged. - - - - - - - - true - Enable Desktop Dragging - Desktop: Rotate the cube with the left mouse button. - - - - true - Enable Panel Dragging - Panel: Rotate the cube with the left mouse button. - - - - true - Enable Desktop Edge Drag Switch - Switch workspaces when dragging a window over the desktop's edge. - - - - - - - - true - Enable Overview Dragging - Overview: Rotate the cube with the left mouse button. - - - - true - Enable Overview Edge Drag Switch - Switch workspaces when dragging a window over the overview's edge. - - - - 80 - Workspace Separation - The pixel gap between adjacent workspaces. - - - - 80 - Horizontal Stretch - The widening factor which ensures that cube sides are visible from the front. - - - - 255 - Active Workspace Opacity - The opacity of the front facing workspace. - - - - 200 - Inactive Workspace Opacity - The opacity of the cube sides. - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/DragGesture.js b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/DragGesture.js deleted file mode 100755 index 5dc4a0ad..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/DragGesture.js +++ /dev/null @@ -1,294 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // -// | \ | ( ` | / | / \ | ) / | | | ) | // -// | | |- `-. |< | | | |-' | | | |-< |- // -// | / | . ) | \ | \ / | \ | | | ) | // -// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // -////////////////////////////////////////////////////////////////////////////////////////// - -// SPDX-FileCopyrightText: Simon Schneegans -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; - -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import {ControlsState} from 'resource:///org/gnome/shell/ui/overviewControls.js'; -import {Workspace} from 'resource:///org/gnome/shell/ui/workspace.js'; - -////////////////////////////////////////////////////////////////////////////////////////// -// In GNOME Shell, SwipeTrackers are used all over the place to capture swipe gestures. // -// There's one for entering the overview, one for switching workspaces in desktop mode, // -// one for switching workspaces in overview mode, one for horizontal scrolling in the // -// app drawer, and many more. The ones used for workspace-switching usually do not // -// respond to single-click dragging but only to multi-touch gestures. We want to be // -// able to rotate the cube with the left mouse button, so we add the gesture defined // -// below to these two SwipeTracker instances (this is done by the _addDragGesture() of // -// the extension class). The gesture is loosely based on the gesture defined here: // -// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/swipeTracker.js#L213 // -// It behaves the same in the regard that it reports update events for horizontal // -// movements. However, it stores vertical movements as well and makes this accessible // -// via the "pitch" property. This is then used for vertical rotations of the cube. // -////////////////////////////////////////////////////////////////////////////////////////// - -const State = { - INACTIVE: 0, // The state will change to PENDING as soon as there is a mouse click. - PENDING: 1, // There was a click, but not enough movement to trigger the gesture. - ACTIVE: 2 // The gesture has been triggered and is in progress. -}; - -// clang-format off -export var DragGesture = - GObject.registerClass({ - Properties: { - 'distance': GObject.ParamSpec.double( - 'distance', 'distance', 'distance', GObject.ParamFlags.READWRITE, 0, Infinity, 0), - 'pitch': GObject.ParamSpec.double( - 'pitch', 'pitch', 'pitch', GObject.ParamFlags.READWRITE, 0, 1, 0), - 'sensitivity': GObject.ParamSpec.double( - 'sensitivity', 'sensitivity', 'sensitivity', GObject.ParamFlags.READWRITE, 1, 10, 1), - }, - Signals: { - 'begin': {param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE]}, - 'update': {param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE]}, - 'end': {param_types: [GObject.TYPE_UINT, GObject.TYPE_DOUBLE]}, - }, - }, - class DragGesture extends GObject.Object { - // clang-format on - _init(actor, mode) { - super._init(); - - this._actor = actor; - this._state = State.INACTIVE; - this._mode = mode; - - // We listen to the 'captured-event' to be able to intercept some other actions. The - // main problem is the long-press action of the desktop background actor. This - // swallows any click events preventing us from dragging the desktop background. - // By connecting to 'captured-event', we have to extra-careful to propagate any - // event we are not interested in. - this._actorConnection1 = actor.connect('captured-event', (a, e) => { - return this._handleEvent(e); - }); - - // Once the input is grabbed, events are delivered directly to the actor, so we have - // also to connect to the normal "event" signal. - this._actorConnection2 = actor.connect('event', (a, e) => { - if (this._lastGrab) { - return this._handleEvent(e); - } - return Clutter.EVENT_PROPAGATE; - }); - } - - // Disconnects from the actor. - destroy() { - this._actor.disconnect(this._actorConnection1); - this._actor.disconnect(this._actorConnection2); - } - - // This is called on every captured event. - _handleEvent(event) { - - // Abort if the gesture is not meant for the current action mode (e.g. either - // Shell.ActionMode.OVERVIEW or Shell.ActionMode.NORMAL). - if (this._mode != Main.actionMode) { - return Clutter.EVENT_PROPAGATE; - } - - // In the overview, we only want to switch workspaces by dragging when in - // window-picker state. - if (Main.actionMode == Shell.ActionMode.OVERVIEW) { - if (Main.overview._overview.controls._stateAdjustment.value != - ControlsState.WINDOW_PICKER) { - return Clutter.EVENT_PROPAGATE; - } - } - - // Ignore touch events on X11. On X11, we get emulated pointer events. - if (!Meta.is_wayland_compositor() && - (event.type() == Clutter.EventType.TOUCH_BEGIN || - event.type() == Clutter.EventType.TOUCH_UPDATE || - event.type() == Clutter.EventType.TOUCH_END)) { - return Clutter.EVENT_PROPAGATE; - } - - // When a mouse button is pressed or a touch event starts, we store the - // corresponding position. The gesture is maybe triggered later, if the pointer was - // moved a little. - if (event.type() == Clutter.EventType.BUTTON_PRESS || - event.type() == Clutter.EventType.TOUCH_BEGIN) { - - const source = global.stage.get_event_actor(event); - - if (source) { - - // Here's a minor hack: In the overview, there are some draggable things like - // window previews which "compete" with this gesture. Sometimes, the cube is - // dragged, sometimes the window previews. So we make sure that we do only start - // the gesture for events which originate from the given actor or from a - // workspace's background. - if (Main.actionMode != Shell.ActionMode.OVERVIEW || source == this._actor || - source.get_parent() instanceof Workspace) { - this._clickPos = event.get_coords(); - this._state = State.PENDING; - } - } - - return Clutter.EVENT_PROPAGATE; - } - - // Abort the pending state if the pointer leaves the actor. - if (event.type() == Clutter.EventType.LEAVE && this._state == State.PENDING) { - this._cancel(); - return Clutter.EVENT_PROPAGATE; - } - - // As soon as the pointer is moved a bit, the drag action becomes active. - if (this._eventIsMotion(event)) { - - // If the mouse button is not pressed, we are not interested in the event. - if (this._state != State.INACTIVE && event.type() == Clutter.EventType.MOTION && - (event.get_state() & Clutter.ModifierType.BUTTON1_MASK) == 0) { - - this._cancel(); - return Clutter.EVENT_PROPAGATE; - } - - const currentPos = event.get_coords(); - - // If we are in the pending state, the gesture may be triggered as soon as the - // pointer is moved enough. - if (this._state == State.PENDING) { - - const threshold = Clutter.Settings.get_default().dnd_drag_threshold; - - if (Math.abs(currentPos[0] - this._clickPos[0]) > threshold || - Math.abs(currentPos[1] - this._clickPos[1]) > threshold) { - - - // When starting a drag in desktop mode, we grab the input so that we can move - // the pointer across windows without loosing the input events. - if (Main.actionMode == Shell.ActionMode.NORMAL) { - const sequence = event.type() == Clutter.EventType.TOUCH_UPDATE ? - event.get_event_sequence() : - null; - - if (!this._grab(event.get_device(), sequence)) { - return Clutter.EVENT_PROPAGATE; - } - } - - this._state = State.ACTIVE; - [this._lastX, this._startY] = currentPos; - this.pitch = 0; - this.emit('begin', event.get_time(), currentPos[0], currentPos[1]); - } - - // Even if the gesture started, we propagate the event so that any other - // gestures may wait for long-presses are canceled properly. - return Clutter.EVENT_PROPAGATE; - } - - // In the active state, we report updates on each movement. - if (this._state == State.ACTIVE) { - - // Compute the horizontal movement relative to the last call. - let deltaX = currentPos[0] - this._lastX; - this._lastX = currentPos[0]; - - // Compute the accumulated pitch relative to the screen height. - this.pitch = (this._startY - currentPos[1]) / global.screen_height; - - // Increase sensitivity. - deltaX *= this.sensitivity; - - // Increase horizontal movement if the cube is rotated vertically. - deltaX *= Util.lerp(1.0, global.workspaceManager.get_n_workspaces(), - Math.abs(this.pitch)); - - this.emit('update', event.get_time(), -deltaX, this.distance); - - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } - - // As soon as the mouse button is released or the touch event ends, we quit the - // gesture. - if (this._eventIsRelease(event)) { - - // If the gesture was active, report an end event. - if (this._state == State.ACTIVE) { - - this._cancel(); - - this.emit('end', event.get_time(), this.distance); - - return Clutter.EVENT_STOP; - } - - // If the gesture was in pending state, set it to inactive again. - this._cancel(); - - return Clutter.EVENT_PROPAGATE; - } - - return Clutter.EVENT_PROPAGATE; - } - - // This aborts any ongoing grab and resets the current state to inactive. - _cancel() { - if (this._lastGrab) { - this._ungrab(); - } - - this._state = State.INACTIVE; - } - - // Makes sure that all events from the pointing device we received last input from is - // passed to the given actor. This is used to ensure that we do not "loose" the touch - // buttons will dragging them around. - _grab(device, sequence) { - this._lastGrab = global.stage.grab(this._actor); - return this._lastGrab != null; - } - - // Releases a grab created with the method above. - _ungrab() { - this._lastGrab.dismiss(); - this._lastGrab = null; - } - - // This is borrowed from here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dnd.js#L214 - _eventIsRelease(event) { - if (event.type() == Clutter.EventType.BUTTON_RELEASE) { - const buttonMask = Clutter.ModifierType.BUTTON1_MASK | - Clutter.ModifierType.BUTTON2_MASK | Clutter.ModifierType.BUTTON3_MASK; - // We only obey the last button release from the device, other buttons may get - // pressed / released during the drag. - return (event.get_state() & buttonMask) == 0; - } else if (event.type() == Clutter.EventType.TOUCH_END) { - // For touch, we only obey the pointer emulating sequence. - return global.display.is_pointer_emulating_sequence(event.get_event_sequence()); - } - - return false; - } - - // This is borrowed from here: - // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/dnd.js#L259 - _eventIsMotion(event) { - return event.type() == Clutter.EventType.MOTION || - (event.type() == Clutter.EventType.TOUCH_UPDATE && - global.display.is_pointer_emulating_sequence(event.get_event_sequence())); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/ImageChooserButton.js b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/ImageChooserButton.js deleted file mode 100755 index b2762797..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/ImageChooserButton.js +++ /dev/null @@ -1,101 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // -// | \ | ( ` | / | / \ | ) / | | | ) | // -// | | |- `-. |< | | | |-' | | | |-< |- // -// | / | . ) | \ | \ / | \ | | | ) | // -// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // -////////////////////////////////////////////////////////////////////////////////////////// - -// SPDX-FileCopyrightText: Simon Schneegans -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import Gio from 'gi://Gio'; -import Gtk from 'gi://Gtk'; -import GObject from 'gi://GObject'; - -import * as utils from './utils.js'; - -const _ = await utils.importGettext(); - -////////////////////////////////////////////////////////////////////////////////////////// -// This is based on a similar class from the Fly-Pie extension (MIT License). // -// https://github.com/Schneegans/Fly-Pie/blob/main/src/prefs/ImageChooserButton.js // -// We only need file chooser buttons for images, so the content. // -////////////////////////////////////////////////////////////////////////////////////////// - -export function registerImageChooserButton() { - - if (GObject.type_from_name('DesktopCubeImageChooserButton') == null) { - GObject.registerClass( - { - GTypeName: 'DesktopCubeImageChooserButton', - Template: `resource:///ui/imageChooserButton.ui`, - InternalChildren: ['button', 'label'], - Properties: { - 'file': GObject.ParamSpec.string('file', 'file', 'file', - GObject.ParamFlags.READWRITE, ''), - }, - }, - class DesktopCubeImageChooserButton extends Gtk.Box { // -------------------------- - _init(params = {}) { - super._init(params); - - this._dialog = new Gtk.Dialog({use_header_bar: true, modal: true, title: ''}); - this._dialog.add_button(_('Select File'), Gtk.ResponseType.OK); - this._dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); - this._dialog.set_default_response(Gtk.ResponseType.OK); - - const fileFilter = new Gtk.FileFilter(); - fileFilter.add_mime_type('image/*'); - - this._fileChooser = new Gtk.FileChooserWidget({ - action: Gtk.FileChooserAction.OPEN, - hexpand: true, - vexpand: true, - height_request: 500, - filter: fileFilter - }); - - this._dialog.get_content_area().append(this._fileChooser); - - this._dialog.connect('response', (dialog, id) => { - if (id == Gtk.ResponseType.OK) { - this.file = this._fileChooser.get_file().get_path(); - } - dialog.hide(); - }); - - this._button.connect('clicked', (button) => { - this._dialog.set_transient_for(button.get_root()); - - this._dialog.show(); - - if (this._file != null) { - this._fileChooser.set_file(this._file); - } - }); - } - - // Returns the currently selected file. - get file() { - return this._file.get_path(); - } - - // This makes the file chooser dialog preselect the given file. - set file(value) { - this._file = Gio.File.new_for_path(value); - - if (this._file.query_exists(null)) { - this._label.label = this._file.get_basename(); - } else { - this._label.label = _('(None)'); - this._file = null; - } - - this.notify('file'); - } - }); - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/Skybox.js b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/Skybox.js deleted file mode 100755 index 022c8810..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/Skybox.js +++ /dev/null @@ -1,182 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // -// | \ | ( ` | / | / \ | ) / | | | ) | // -// | | |- `-. |< | | | |-' | | | |-< |- // -// | / | . ) | \ | \ / | \ | | | ) | // -// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // -////////////////////////////////////////////////////////////////////////////////////////// - -// SPDX-FileCopyrightText: Simon Schneegans -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import Gio from 'gi://Gio'; -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Cogl from 'gi://Cogl'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import * as utils from './utils.js'; - -////////////////////////////////////////////////////////////////////////////////////////// -// This file contains two classes, the Skybox (which is an actor) and the SkyboxEffect, // -// which is a Shell.GLSLEffect which is applied to the Skybox actor. // -// // -// SkyboxEffect loads a given texture and interprets it as a 360° panorama in // -// equirectangular projection. It uses the current perspective of the stage to draw a // -// perspectively correct portion of this panorama. It has an additional pitch and yaw // -// parameter controlling the horizontal and vertical rotation of the camera. // -////////////////////////////////////////////////////////////////////////////////////////// - -// clang-format off -var SkyboxEffect = GObject.registerClass({ - Properties: { - 'yaw': GObject.ParamSpec.double('yaw', 'yaw', 'yaw', GObject.ParamFlags.READWRITE, - -2 * Math.PI, 2 * Math.PI, 0), - 'pitch': GObject.ParamSpec.double('pitch', 'pitch', 'pitch', GObject.ParamFlags.READWRITE, - -0.5 * Math.PI, 0.5 * Math.PI, 0), - }, - }, class SkyboxEffect extends Shell.GLSLEffect { - // clang-format on - _init(file) { - super._init(); - - this._texture = null; - - // Attempt to load the texture. - this._loadTexture(file) - .then(texture => { - this._texture = texture; - this.queue_repaint(); - }) - .catch(error => { - utils.debug(error); - }); - - // Redraw if either the pitch or the yaw changes. - this.connect('notify::yaw', () => {this.queue_repaint()}); - this.connect('notify::pitch', () => {this.queue_repaint()}); - }; - - // This is called once to setup the Cogl.Pipeline. - vfunc_build_pipeline() { - - // In the vertex shader, we compute the view space position of the actor's corners. - this.add_glsl_snippet(Shell.SnippetHook.VERTEX, 'varying vec4 vsPos;', - 'vsPos = cogl_modelview_matrix * cogl_position_in;', false); - - const fragmentDeclares = ` - varying vec4 vsPos; - uniform sampler2D uTexture; - uniform float uPitch; - uniform float uYaw; - - mat3 getPitch() { - float s = sin(uPitch); - float c = cos(uPitch); - return mat3(1.0, 0.0, 0.0, 0.0, c, s, 0.0, -s, c); - } - - mat3 getYaw() { - float s = sin(uYaw); - float c = cos(uYaw); - return mat3(c, 0.0, -s, 0.0, 1.0, 0.0, s, 0.0, c); - } - `; - - // The fragment shader uses the interpolated viewspace position to compute a view - // ray. This ray is rotated according to the pitch and yaw values. - const fragmentCode = ` - // Rotate the view ray. - vec3 view = getYaw() * getPitch() * normalize(vsPos.xyz); - - // Compute equirectangular projection. - const float pi = 3.14159265359; - float x = 0.5 + 0.5 * atan(view.x, -view.z) / pi; - float y = acos(view.y) / pi; - - cogl_color_out = texture2D(uTexture, vec2(x, y)); - `; - - this.add_glsl_snippet(Shell.SnippetHook.FRAGMENT, fragmentDeclares, fragmentCode, - false); - } - - // For each draw call, we have to set some uniform values. - vfunc_paint_target(node, paintContext) { - if (this._texture) { - this.get_pipeline().set_layer_texture(0, this._texture.get_texture()); - this.set_uniform_float(this.get_uniform_location('uTexture'), 1, [0]); - this.set_uniform_float(this.get_uniform_location('uPitch'), 1, [this.pitch]); - this.set_uniform_float(this.get_uniform_location('uYaw'), 1, [this.yaw]); - - super.vfunc_paint_target(node, paintContext); - } - } - - // Load a texture asynchronously. - async _loadTexture(file) { - return new Promise((resolve, reject) => { - const stream = Gio.File.new_for_path(file).read(null); - GdkPixbuf.Pixbuf.new_from_stream_async(stream, null, (obj, result) => { - const FORMATS = [ - Cogl.PixelFormat.G_8, - Cogl.PixelFormat.RG_88, - Cogl.PixelFormat.RGB_888, - Cogl.PixelFormat.RGBA_8888, - ]; - - try { - const pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(result); - const texture = new Clutter.Image(); - texture.set_data(pixbuf.get_pixels(), FORMATS[pixbuf.get_n_channels() - 1], - pixbuf.get_width(), pixbuf.get_height(), - pixbuf.get_rowstride()); - resolve(texture); - } catch (error) { - reject(error); - } - }); - }); - } -}); - -////////////////////////////////////////////////////////////////////////////////////////// -// The Skybox is a simple actor which applies the above effect to itself. It also has // -// the pitch and yaw properties - these are directly forwarded to the effect. // -////////////////////////////////////////////////////////////////////////////////////////// - -// clang-format off -export var Skybox = GObject.registerClass({ - Properties: { - 'yaw': GObject.ParamSpec.double('yaw', 'yaw', 'yaw', GObject.ParamFlags.READWRITE, - -2 * Math.PI, 2 * Math.PI, 0), - 'pitch': GObject.ParamSpec.double('pitch', 'pitch', 'pitch', GObject.ParamFlags.READWRITE, - -0.5 * Math.PI, 0.5 * Math.PI, 0), - } - }, class Skybox extends Clutter.Actor { - // clang-format on - _init(file) { - super._init(); - - // Apply the effect. - this._effect = new SkyboxEffect(file); - this.add_effect(this._effect); - - // Make sure that the overview background is transparent. - Main.uiGroup.add_style_class_name('desktop-cube-panorama-enabled'); - - // Forward the yaw and pitch values. - this.bind_property('yaw', this._effect, 'yaw', GObject.BindingFlags.NONE); - this.bind_property('pitch', this._effect, 'pitch', GObject.BindingFlags.NONE); - - // Revert to the original overview background appearance. - this.connect('destroy', () => { - Main.uiGroup.remove_style_class_name('desktop-cube-panorama-enabled'); - }); - } -}); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/utils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/utils.js deleted file mode 100755 index 2f3e0159..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/src/utils.js +++ /dev/null @@ -1,42 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////////// -// ,-. ,--. ,-. , , ,---. ,-. ;-. ,-. . . ,-. ,--. // -// | \ | ( ` | / | / \ | ) / | | | ) | // -// | | |- `-. |< | | | |-' | | | |-< |- // -// | / | . ) | \ | \ / | \ | | | ) | // -// `-' `--' `-' ' ` ' `-' ' `-' `--` `-' `--' // -////////////////////////////////////////////////////////////////////////////////////////// - -// SPDX-FileCopyrightText: Simon Schneegans -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -// This method can be used to write a message to GNOME Shell's log. This is enhances -// the standard log() functionality by prepending the extension's name and the location -// where the message was logged. As the extensions name is part of the location, you -// can more effectively watch the log output of GNOME Shell: -// journalctl -f -o cat | grep -E 'desktop-cube|' -// This method is based on a similar script from the Fly-Pie GNOME Shell extension which -// os published under the MIT License (https://github.com/Schneegans/Fly-Pie). -export function debug(message) { - const stack = new Error().stack.split('\n'); - - // Remove debug() function call from stack. - stack.shift(); - - // Find the index of the extension directory (e.g. desktop-cube@schneegans.github.com) - // in the stack entry. We do not want to print the entire absolute file path. - const extensionRoot = stack[0].indexOf('desktop-cube@schneegans.github.com'); - - console.log('[' + stack[0].slice(extensionRoot) + '] ' + message); -} - -// This method can be used to import gettext. This is done differently in the -// GNOME Shell process and in the preferences process. -export async function importGettext() { - if (typeof global === 'undefined') { - return (await import('resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js')) - .gettext; - } - return (await import('resource:///org/gnome/shell/extensions/extension.js')).gettext; -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/stylesheet.css deleted file mode 100755 index 82ed00c2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/desktop-cube@schneegans.github.com/stylesheet.css +++ /dev/null @@ -1,20 +0,0 @@ -/* -SPDX-FileCopyrightText: Simon Schneegans -SPDX-License-Identifier: CC0-1.0 -*/ - -/* -This ensures that the overview background is transparent, so that the background -panorama becomes visible. -*/ -.desktop-cube-panorama-enabled #overviewGroup { - background: transparent; -} - -/* -This ensures that the background during workspace switches becomes transparent, so that -the background panorama becomes visible. -*/ -.desktop-cube-panorama-enabled .workspace-animation { - background-color: transparent; -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/config.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/config.js deleted file mode 100755 index 17403638..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/config.js +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -export default { - PACKAGE_VERSION: 57, - PACKAGE_URL: 'https://github.com/GSConnect/gnome-shell-extension-gsconnect', - PACKAGE_BUGREPORT: 'https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/new', - PACKAGE_DATADIR: '/usr/local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io', - PACKAGE_LOCALEDIR: '/usr/local/share/locale', - GSETTINGS_SCHEMA_DIR: '/usr/local/share/glib-2.0/schemas', - GNOME_SHELL_LIBDIR: '/usr/local/lib64', - - APP_ID: 'org.gnome.Shell.Extensions.GSConnect', - APP_PATH: '/org/gnome/Shell/Extensions/GSConnect', - - IS_USER: false, - - // External binary paths - OPENSSL_PATH: 'openssl', - SSHADD_PATH: 'ssh-add', - SSHKEYGEN_PATH: 'ssh-keygen', - FFMPEG_PATH: 'ffmpeg', -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/extension.js deleted file mode 100755 index 9d960ac1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/extension.js +++ /dev/null @@ -1,407 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as QuickSettings from 'resource:///org/gnome/shell/ui/quickSettings.js'; - -// Bootstrap -import { - Extension, - gettext as _, - ngettext -} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import Config from './config.js'; -import * as Clipboard from './shell/clipboard.js'; -import * as Device from './shell/device.js'; -import * as Keybindings from './shell/keybindings.js'; -import * as Notification from './shell/notification.js'; -import * as Input from './shell/input.js'; -import * as Utils from './shell/utils.js'; -import * as Remote from './utils/remote.js'; -import setup from './utils/setup.js'; - -const QuickSettingsMenu = Main.panel.statusArea.quickSettings; - - -/** - * A System Indicator used as the hub for spawning device indicators and - * indicating that the extension is active when there are none. - */ -const ServiceToggle = GObject.registerClass({ - GTypeName: 'GSConnectServiceIndicator', -}, class ServiceToggle extends QuickSettings.QuickMenuToggle { - - _init() { - super._init({ - title: 'GSConnect', - toggleMode: true, - }); - - this.set({iconName: 'org.gnome.Shell.Extensions.GSConnect-symbolic'}); - - // Set QuickMenuToggle header. - this.menu.setHeader('org.gnome.Shell.Extensions.GSConnect-symbolic', 'GSConnect', - _('Sync between your devices')); - - this._menus = {}; - - this._keybindings = new Keybindings.Manager(); - - // GSettings - this.settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect', - null - ), - path: '/org/gnome/shell/extensions/gsconnect/', - }); - - // Bind the toggle to enabled key - this.settings.bind('enabled', - this, 'checked', - Gio.SettingsBindFlags.DEFAULT); - - this._enabledId = this.settings.connect( - 'changed::enabled', - this._onEnabledChanged.bind(this) - ); - - this._panelModeId = this.settings.connect( - 'changed::show-indicators', - this._sync.bind(this) - ); - - // Service Proxy - this.service = new Remote.Service(); - - this._deviceAddedId = this.service.connect( - 'device-added', - this._onDeviceAdded.bind(this) - ); - - this._deviceRemovedId = this.service.connect( - 'device-removed', - this._onDeviceRemoved.bind(this) - ); - - this._serviceChangedId = this.service.connect( - 'notify::active', - this._onServiceChanged.bind(this) - ); - - // Service Menu -> Devices Section - this.deviceSection = new PopupMenu.PopupMenuSection(); - this.deviceSection.actor.add_style_class_name('gsconnect-device-section'); - this.settings.bind( - 'show-indicators', - this.deviceSection.actor, - 'visible', - Gio.SettingsBindFlags.INVERT_BOOLEAN - ); - this.menu.addMenuItem(this.deviceSection); - - // Service Menu -> Separator - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - - // Service Menu -> "Mobile Settings" - this.menu.addSettingsAction( - _('Mobile Settings'), - 'org.gnome.Shell.Extensions.GSConnect.Preferences.desktop'); - - // Prime the service - this._initService(); - } - - async _initService() { - try { - if (this.settings.get_boolean('enabled')) - await this.service.start(); - else - await this.service.reload(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - _sync() { - const available = this.service.devices.filter(device => { - return (device.connected && device.paired); - }); - const panelMode = this.settings.get_boolean('show-indicators'); - - // Hide status indicator if in Panel mode or no devices are available - serviceIndicator._indicator.visible = (!panelMode && available.length); - - // Show device indicators in Panel mode if available - for (const device of this.service.devices) { - const isAvailable = available.includes(device); - const indicator = Main.panel.statusArea[device.g_object_path]; - - indicator.visible = panelMode && isAvailable; - - const menu = this._menus[device.g_object_path]; - menu.actor.visible = !panelMode && isAvailable; - menu._title.actor.visible = !panelMode && isAvailable; - } - - // Set subtitle on Quick Settings tile - if (available.length === 1) { - this.subtitle = available[0].name; - } else if (available.length > 1) { - // TRANSLATORS: %d is the number of devices connected - this.subtitle = ngettext( - '%d Connected', - '%d Connected', - available.length - ).format(available.length); - } else { - this.subtitle = null; - } - } - - _onDeviceChanged(device, changed, invalidated) { - try { - const properties = changed.deepUnpack(); - - if (properties.hasOwnProperty('Connected') || - properties.hasOwnProperty('Paired')) - this._sync(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - _onDeviceAdded(service, device) { - try { - // Device Indicator - const indicator = new Device.Indicator({device: device}); - Main.panel.addToStatusArea(device.g_object_path, indicator); - - // Device Menu - const menu = new Device.Menu({ - device: device, - menu_type: 'list', - }); - this._menus[device.g_object_path] = menu; - this.deviceSection.addMenuItem(menu); - - // Device Settings - device.settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect.Device', - true - ), - path: `/org/gnome/shell/extensions/gsconnect/device/${device.id}/`, - }); - - // Keyboard Shortcuts - device.__keybindingsChangedId = device.settings.connect( - 'changed::keybindings', - this._onDeviceKeybindingsChanged.bind(this, device) - ); - this._onDeviceKeybindingsChanged(device); - - // Watch the for status changes - device.__deviceChangedId = device.connect( - 'g-properties-changed', - this._onDeviceChanged.bind(this) - ); - - this._sync(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - _onDeviceRemoved(service, device, sync = true) { - try { - // Stop watching for status changes - if (device.__deviceChangedId) - device.disconnect(device.__deviceChangedId); - - // Release keybindings - if (device.__keybindingsChangedId) { - device.settings.disconnect(device.__keybindingsChangedId); - device._keybindings.map(id => this._keybindings.remove(id)); - } - - // Destroy the indicator - Main.panel.statusArea[device.g_object_path].destroy(); - - // Destroy the menu - this._menus[device.g_object_path].destroy(); - delete this._menus[device.g_object_path]; - - if (sync) - this._sync(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - _onDeviceKeybindingsChanged(device) { - try { - // Reset any existing keybindings - if (device.hasOwnProperty('_keybindings')) - device._keybindings.map(id => this._keybindings.remove(id)); - - device._keybindings = []; - - // Get the keybindings - const keybindings = device.settings.get_value('keybindings').deepUnpack(); - - // Apply the keybindings - for (const [action, accelerator] of Object.entries(keybindings)) { - const [, name, parameter] = Gio.Action.parse_detailed_name(action); - - const actionId = this._keybindings.add( - accelerator, - () => device.action_group.activate_action(name, parameter) - ); - - if (actionId !== 0) - device._keybindings.push(actionId); - } - } catch (e) { - logError(e, 'GSConnect'); - } - } - - async _onEnabledChanged(settings, key) { - try { - if (this.settings.get_boolean('enabled')) - await this.service.start(); - else - await this.service.stop(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - async _onServiceChanged(service, pspec) { - try { - // If it's enabled, we should try to restart now - if (this.settings.get_boolean('enabled')) - await this.service.start(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - destroy() { - // Unhook from Remote.Service - if (this.service) { - this.service.disconnect(this._serviceChangedId); - this.service.disconnect(this._deviceAddedId); - this.service.disconnect(this._deviceRemovedId); - - for (const device of this.service.devices) - this._onDeviceRemoved(this.service, device, false); - - if (!this.settings.get_boolean('keep-alive-when-locked')) - this.service.stop(); - this.service.destroy(); - } - - // Disconnect any keybindings - this._keybindings.destroy(); - - // Disconnect from any GSettings changes - this.settings.disconnect(this._enabledId); - this.settings.disconnect(this._panelModeId); - this.settings.run_dispose(); - - // Destroy the PanelMenu.SystemIndicator actors - this.menu.destroy(); - - super.destroy(); - } -}); - -const ServiceIndicator = GObject.registerClass( -class ServiceIndicator extends QuickSettings.SystemIndicator { - _init() { - super._init(); - - // Create the icon for the indicator - this._indicator = this._addIndicator(); - this._indicator.icon_name = 'org.gnome.Shell.Extensions.GSConnect-symbolic'; - // Hide the indicator by default - this._indicator.visible = false; - - // Create the toggle menu and associate it with the indicator - this.quickSettingsItems.push(new ServiceToggle()); - - // Add the indicator to the panel and the toggle to the menu - QuickSettingsMenu.addExternalIndicator(this); - } - - destroy() { - // Set enabled state to false to kill the service on destroy - this.quickSettingsItems.forEach(item => item.destroy()); - // Destroy the indicator - this._indicator.destroy(); - super.destroy(); - } -}); - -let serviceIndicator = null; - -export default class GSConnectExtension extends Extension { - lockscreenInput = null; - - constructor(metadata) { - super(metadata); - setup(this.path); - - // If installed as a user extension, this checks the permissions - // on certain critical files in the extension directory - // to ensure that they have the executable bit set, - // and makes them executable if not. Some packaging methods - // (particularly GitHub Actions artifacts) automatically remove - // executable bits from all contents, presumably for security. - Utils.ensurePermissions(); - - // If installed as a user extension, this will install the Desktop entry, - // DBus and systemd service files necessary for DBus activation and - // GNotifications. Since there's no uninit()/uninstall() hook for extensions - // and they're only used *by* GSConnect, they should be okay to leave. - Utils.installService(); - - // These modify the notification source for GSConnect's GNotifications and - // need to be active even when the extension is disabled (eg. lock screen). - // Since they *only* affect notifications from GSConnect, it should be okay - // to leave them applied. - Notification.patchGSConnectNotificationSource(); - Notification.patchGtkNotificationDaemon(); - - // This watches for the service to start and exports a custom clipboard - // portal for use on Wayland - Clipboard.watchService(); - } - - enable() { - serviceIndicator = new ServiceIndicator(); - Notification.patchGtkNotificationSources(); - - this.lockscreenInput = new Input.LockscreenRemoteAccess(); - this.lockscreenInput.patchInhibitor(); - } - - disable() { - serviceIndicator.destroy(); - serviceIndicator = null; - Notification.unpatchGtkNotificationSources(); - - if (this.lockscreenInput) { - this.lockscreenInput.unpatchInhibitor(); - this.lockscreenInput = null; - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences deleted file mode 100755 index b16ddc7d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env -S gjs -m - -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -// -*- mode: js; -*- - -import Gdk from 'gi://Gdk?version=3.0'; -import 'gi://GdkPixbuf?version=2.0'; -import Gio from 'gi://Gio?version=2.0'; -import GLib from 'gi://GLib?version=2.0'; -import GObject from 'gi://GObject?version=2.0'; -import Gtk from 'gi://Gtk?version=3.0'; - -import system from 'system'; - -import './preferences/init.js'; -import {Window} from './preferences/service.js'; -import Config from './config.js'; - -import('gi://GioUnix?version=2.0').catch(() => {}); // Set version for optional dependency - - -/** - * Class representing the GSConnect service daemon. - */ -const Preferences = GObject.registerClass({ - GTypeName: 'GSConnectPreferences', - Implements: [Gio.ActionGroup], -}, class Preferences extends Gtk.Application { - - _init() { - super._init({ - application_id: 'org.gnome.Shell.Extensions.GSConnect.Preferences', - resource_base_path: '/org/gnome/Shell/Extensions/GSConnect', - }); - - GLib.set_prgname('gsconnect-preferences'); - GLib.set_application_name(_('GSConnect Preferences')); - } - - vfunc_activate() { - if (this._window === undefined) { - this._window = new Window({ - application: this, - }); - } - - this._window.present(); - } - - vfunc_startup() { - super.vfunc_startup(); - - // Init some resources - const provider = new Gtk.CssProvider(); - provider.load_from_resource(`${Config.APP_PATH}/application.css`); - Gtk.StyleContext.add_provider_for_screen( - Gdk.Screen.get_default(), - provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - const actions = [ - ['refresh', null], - ['connect', GLib.VariantType.new('s')], - ]; - - for (const [name, type] of actions) { - const action = new Gio.SimpleAction({ - name: name, - parameter_type: type, - }); - this.add_action(action); - } - } - - vfunc_activate_action(action_name, parameter) { - try { - const paramArray = []; - - if (parameter instanceof GLib.Variant) - paramArray[0] = parameter; - - this.get_dbus_connection().call( - 'org.gnome.Shell.Extensions.GSConnect', - '/org/gnome/Shell/Extensions/GSConnect', - 'org.freedesktop.Application', - 'ActivateAction', - GLib.Variant.new('(sava{sv})', [action_name, paramArray, {}]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - null - ); - } catch (e) { - logError(e); - } - } -}); - -await (new Preferences()).runAsync([system.programInvocationName].concat(ARGV)); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ar/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ar/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 78e91a6f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ar/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/be/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/be/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 5e783fb0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/be/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ca/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ca/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index cfb89881..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ca/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/cs/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/cs/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 281c7578..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/cs/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/da/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/da/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 3fcc2a5a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/da/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/de/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/de/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 9ae06773..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/de/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/el/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/el/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index aa446e31..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/el/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/es/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/es/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index a2fa920a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/es/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/et/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/et/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index e8ec924a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/et/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fa/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fa/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index d792ee91..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fa/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fi/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fi/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 1ecfc388..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fi/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 80b6edbb..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fy/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fy/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 7b7cc55d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/fy/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/gl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/gl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index a26f6b62..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/gl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/he/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/he/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 6643a6ab..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/he/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/hu/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/hu/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 783cc39a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/hu/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/id/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/id/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 15e8fa04..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/id/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/it/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/it/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 499500d3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/it/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ko/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ko/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 16bb28eb..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ko/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/lt/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/lt/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 13f9d1c6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/lt/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/nl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/nl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index e01ae547..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/nl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/nl_BE/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/nl_BE/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index f03a29f3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/nl_BE/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 73ed9e24..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pl/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pt/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pt/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 8aa61374..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pt/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pt_BR/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pt_BR/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index bc26e361..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/pt_BR/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ru/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ru/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index d504fad4..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/ru/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sk/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sk/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index f6831f55..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sk/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index a2a03e40..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sr@latin/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sr@latin/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index ddb718ce..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sr@latin/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sv/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sv/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index d17330ce..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/sv/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/tr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/tr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 761537d9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/tr/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/uk/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/uk/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index a47d1e67..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/uk/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/zh_CN/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/zh_CN/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index 284c9303..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/zh_CN/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/zh_TW/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/zh_TW/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo deleted file mode 100755 index f47aad68..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/locale/zh_TW/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/metadata.json deleted file mode 100755 index a50493f4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "GSConnect is a complete implementation of KDE Connect especially for GNOME Shell with Nautilus, Chrome and Firefox integration. It does not rely on the KDE Connect desktop application and will not work with it installed.\n\nKDE Connect allows devices to securely share content like notifications or files and other features like SMS messaging and remote control. The KDE Connect team has applications for Linux, BSD, Android, Sailfish, iOS, macOS and Windows.\n\nPlease report issues on Github!", - "name": "GSConnect", - "shell-version": [ - "46" - ], - "url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki", - "uuid": "gsconnect@andyholmes.github.io", - "version": 57 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py deleted file mode 100755 index 05a71b0f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py +++ /dev/null @@ -1,212 +0,0 @@ -# SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -# -# SPDX-License-Identifier: GPL-2.0-or-later - -""" -nautilus-gsconnect.py - A Nautilus extension for sending files via GSConnect. - -A great deal of credit and appreciation is owed to the indicator-kdeconnect -developers for the sister Python script 'kdeconnect-send-nautilus.py': - -https://github.com/Bajoja/indicator-kdeconnect/blob/master/data/extensions/kdeconnect-send-nautilus.py -""" - -import gettext -import os.path -import sys - -import gi - -gi.require_version("Gio", "2.0") -gi.require_version("GLib", "2.0") -gi.require_version("GObject", "2.0") -from gi.repository import Gio, GLib, GObject - - -# Host application detection -# -# Nemo seems to reliably identify itself as 'nemo' in argv[0], so we -# can test for that. Nautilus detection is less reliable, so don't try. -# See https://github.com/linuxmint/nemo-extensions/issues/330 -if "nemo" in sys.argv[0].lower(): - # Host runtime is nemo-python - gi.require_version("Nemo", "3.0") - from gi.repository import Nemo as FileManager -else: - # Otherwise, just assume it's nautilus-python - from gi.repository import Nautilus as FileManager - - -SERVICE_NAME = "org.gnome.Shell.Extensions.GSConnect" -SERVICE_PATH = "/org/gnome/Shell/Extensions/GSConnect" - -# Init gettext translations -LOCALE_DIR = os.path.join( - GLib.get_user_data_dir(), - "gnome-shell", - "extensions", - "gsconnect@andyholmes.github.io", - "locale", -) - -if not os.path.exists(LOCALE_DIR): - LOCALE_DIR = None - -try: - i18n = gettext.translation(SERVICE_NAME, localedir=LOCALE_DIR) - _ = i18n.gettext - -except (IOError, OSError) as e: - print("GSConnect: {0}".format(str(e))) - i18n = gettext.translation( - SERVICE_NAME, localedir=LOCALE_DIR, fallback=True - ) - _ = i18n.gettext - - -class GSConnectShareExtension(GObject.Object, FileManager.MenuProvider): - """A context menu for sending files via GSConnect.""" - - def __init__(self): - """Initialize the DBus ObjectManager.""" - GObject.Object.__init__(self) - - self.devices = {} - - Gio.DBusProxy.new_for_bus( - Gio.BusType.SESSION, - Gio.DBusProxyFlags.DO_NOT_AUTO_START, - None, - SERVICE_NAME, - SERVICE_PATH, - "org.freedesktop.DBus.ObjectManager", - None, - self._init_async, - None, - ) - - def _init_async(self, proxy, res, user_data): - proxy = proxy.new_for_bus_finish(res) - proxy.connect("notify::g-name-owner", self._on_name_owner_changed) - proxy.connect("g-signal", self._on_g_signal) - - self._on_name_owner_changed(proxy, None) - - def _on_g_signal(self, proxy, sender_name, signal_name, parameters): - # Wait until the service is ready - if proxy.props.g_name_owner is None: - return - - objects = parameters.unpack() - - if signal_name == "InterfacesAdded": - for object_path, props in objects.items(): - props = props["org.gnome.Shell.Extensions.GSConnect.Device"] - - self.devices[object_path] = ( - props["Name"], - Gio.DBusActionGroup.get( - proxy.get_connection(), SERVICE_NAME, object_path - ), - ) - elif signal_name == "InterfacesRemoved": - for object_path in objects: - try: - del self.devices[object_path] - except KeyError: - pass - - def _on_name_owner_changed(self, proxy, pspec): - # Wait until the service is ready - if proxy.props.g_name_owner is None: - self.devices = {} - else: - proxy.call( - "GetManagedObjects", - None, - Gio.DBusCallFlags.NO_AUTO_START, - -1, - None, - self._get_managed_objects, - None, - ) - - def _get_managed_objects(self, proxy, res, user_data): - objects = proxy.call_finish(res)[0] - - for object_path, props in objects.items(): - props = props["org.gnome.Shell.Extensions.GSConnect.Device"] - if not props: - continue - - self.devices[object_path] = ( - props["Name"], - Gio.DBusActionGroup.get( - proxy.get_connection(), SERVICE_NAME, object_path - ), - ) - - def send_files(self, menu, files, action_group): - """Send *files* to *device_id*.""" - for file in files: - variant = GLib.Variant("(sb)", (file.get_uri(), False)) - action_group.activate_action("shareFile", variant) - - def get_file_items(self, *args): - """Return a list of select files to be sent.""" - # 'args' will depend on the Nautilus API version. - # * Nautilus 4.0: - # `[files: List[Nautilus.FileInfo]]` - # * Nautilus 3.0: - # `[window: Gtk.Widget, files: List[Nautilus.FileInfo]]` - files = args[-1] - - # Only accept regular files - for uri in files: - if uri.get_uri_scheme() != "file" or uri.is_directory(): - return () - - # Enumerate capable devices - devices = [] - - for name, action_group in self.devices.values(): - if action_group.get_action_enabled("shareFile"): - devices.append([name, action_group]) - - # No capable devices; don't show menu entry - if not devices: - return () - - # If there's exactly 1 device, no submenu - if len(devices) == 1: - name, action_group = devices[0] - menu = FileManager.MenuItem( - name="GSConnectShareExtension::Device" + name, - # TRANSLATORS: Send to , for file manager - # context menu - label=_("Send to %s") % name, - ) - menu.connect("activate", self.send_files, files, action_group) - - else: - # Context Menu Item - menu = FileManager.MenuItem( - name="GSConnectShareExtension::Devices", - label=_("Send To Mobile Device"), - ) - - # Context Submenu - submenu = FileManager.Menu() - menu.set_submenu(submenu) - - # Context Submenu Items - for name, action_group in devices: - item = FileManager.MenuItem( - name="GSConnectShareExtension::Device" + name, label=name - ) - - item.connect("activate", self.send_files, files, action_group) - - submenu.append_item(item) - - return (menu,) diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/org.gnome.Shell.Extensions.GSConnect.gresource b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/org.gnome.Shell.Extensions.GSConnect.gresource deleted file mode 100755 index 17fe4851..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/org.gnome.Shell.Extensions.GSConnect.gresource and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/device.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/device.js deleted file mode 100755 index 76fc0c73..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/device.js +++ /dev/null @@ -1,1111 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import Pango from 'gi://Pango'; - -import Config from '../config.js'; -import plugins from '../service/plugins/index.js'; -import * as Keybindings from './keybindings.js'; - - -// Build a list of plugins and shortcuts for devices -const DEVICE_PLUGINS = []; -const DEVICE_SHORTCUTS = {}; - -for (const name in plugins) { - const module = plugins[name]; - - if (module.Metadata === undefined) - continue; - - // Plugins - DEVICE_PLUGINS.push(name); - - // Shortcuts (GActions without parameters) - for (const [name, action] of Object.entries(module.Metadata.actions)) { - if (action.parameter_type === null) - DEVICE_SHORTCUTS[name] = [action.icon_name, action.label]; - } -} - - -/** - * A Gtk.ListBoxHeaderFunc for sections that adds separators between each row. - * - * @param {Gtk.ListBoxRow} row - The current row - * @param {Gtk.ListBoxRow} before - The previous row - */ -export function rowSeparators(row, before) { - const header = row.get_header(); - - if (before === null) { - if (header !== null) - header.destroy(); - - return; - } - - if (header === null) - row.set_header(new Gtk.Separator({visible: true})); -} - - -/** - * A Gtk.ListBoxSortFunc for SectionRow rows - * - * @param {Gtk.ListBoxRow} row1 - The first row - * @param {Gtk.ListBoxRow} row2 - The second row - * @return {number} -1, 0 or 1 - */ -export function titleSortFunc(row1, row2) { - if (!row1.title || !row2.title) - return 0; - - return row1.title.localeCompare(row2.title); -} - - -/** - * A row for a section of settings - */ -const SectionRow = GObject.registerClass({ - GTypeName: 'GSConnectPreferencesSectionRow', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-section-row.ui', - Children: ['icon-image', 'title-label', 'subtitle-label'], - Properties: { - 'gicon': GObject.ParamSpec.object( - 'gicon', - 'GIcon', - 'A GIcon for the row', - GObject.ParamFlags.READWRITE, - Gio.Icon.$gtype - ), - 'icon-name': GObject.ParamSpec.string( - 'icon-name', - 'Icon Name', - 'An icon name for the row', - GObject.ParamFlags.READWRITE, - null - ), - 'subtitle': GObject.ParamSpec.string( - 'subtitle', - 'Subtitle', - 'A subtitle for the row', - GObject.ParamFlags.READWRITE, - null - ), - 'title': GObject.ParamSpec.string( - 'title', - 'Title', - 'A title for the row', - GObject.ParamFlags.READWRITE, - null - ), - 'widget': GObject.ParamSpec.object( - 'widget', - 'Widget', - 'An action widget for the row', - GObject.ParamFlags.READWRITE, - Gtk.Widget.$gtype - ), - }, -}, class SectionRow extends Gtk.ListBoxRow { - - _init(params = {}) { - super._init(); - - // NOTE: we can't pass construct properties to _init() because the - // template children are not assigned until after it runs. - this.freeze_notify(); - Object.assign(this, params); - this.thaw_notify(); - } - - get icon_name() { - return this.icon_image.icon_name; - } - - set icon_name(icon_name) { - if (this.icon_name === icon_name) - return; - - this.icon_image.visible = !!icon_name; - this.icon_image.icon_name = icon_name; - this.notify('icon-name'); - } - - get gicon() { - return this.icon_image.gicon; - } - - set gicon(gicon) { - if (this.gicon === gicon) - return; - - this.icon_image.visible = !!gicon; - this.icon_image.gicon = gicon; - this.notify('gicon'); - } - - get title() { - return this.title_label.label; - } - - set title(text) { - if (this.title === text) - return; - - this.title_label.visible = !!text; - this.title_label.label = text; - this.notify('title'); - } - - get subtitle() { - return this.subtitle_label.label; - } - - set subtitle(text) { - if (this.subtitle === text) - return; - - this.subtitle_label.visible = !!text; - this.subtitle_label.label = text; - this.notify('subtitle'); - } - - get widget() { - if (this._widget === undefined) - this._widget = null; - - return this._widget; - } - - set widget(widget) { - if (this.widget === widget) - return; - - if (this.widget instanceof Gtk.Widget) - this.widget.destroy(); - - // Add the widget - this._widget = widget; - this.get_child().attach(widget, 2, 0, 1, 2); - this.notify('widget'); - } -}); - - -/** - * Command Editor Dialog - */ -const CommandEditor = GObject.registerClass({ - GTypeName: 'GSConnectPreferencesCommandEditor', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-command-editor.ui', - Children: [ - 'cancel-button', 'save-button', - 'command-entry', 'name-entry', 'command-chooser', - ], -}, class CommandEditor extends Gtk.Dialog { - - _onBrowseCommand(entry, icon_pos, event) { - this.command_chooser.present(); - } - - _onCommandChosen(dialog, response_id) { - if (response_id === Gtk.ResponseType.OK) - this.command_entry.text = dialog.get_filename(); - - dialog.hide(); - } - - _onEntryChanged(entry, pspec) { - this.save_button.sensitive = (this.command_name && this.command_line); - } - - get command_line() { - return this.command_entry.text; - } - - set command_line(text) { - this.command_entry.text = text; - } - - get command_name() { - return this.name_entry.text; - } - - set command_name(text) { - this.name_entry.text = text; - } -}); - - -/** - * A widget for configuring a remote device. - */ -export const Panel = GObject.registerClass({ - GTypeName: 'GSConnectPreferencesDevicePanel', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device being configured', - GObject.ParamFlags.READWRITE, - GObject.Object.$gtype - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-device-panel.ui', - Children: [ - 'sidebar', 'stack', 'infobar', - - // Sharing - 'sharing', 'sharing-page', - 'desktop-list', 'clipboard', 'clipboard-sync', 'mousepad', 'mpris', 'systemvolume', - 'share', 'share-list', 'receive-files', 'receive-directory', - - // Battery - 'battery', - 'battery-device-label', 'battery-device', 'battery-device-list', - 'battery-system-label', 'battery-system', 'battery-system-list', - 'battery-custom-notification-value', - - // RunCommand - 'runcommand', 'runcommand-page', - 'command-list', 'command-add', - - // Notifications - 'notification', 'notification-page', - 'notification-list', 'notification-apps', - - // Telephony - 'telephony', 'telephony-page', - 'ringing-list', 'ringing-volume', 'talking-list', 'talking-volume', - - // Shortcuts - 'shortcuts-page', - 'shortcuts-actions', 'shortcuts-actions-title', 'shortcuts-actions-list', - - // Advanced - 'advanced-page', - 'plugin-list', 'experimental-list', - - 'device-menu', - ], -}, class Panel extends Gtk.Grid { - - _init(device) { - super._init({ - device: device, - }); - - // GSettings - this.settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect.Device', - true - ), - path: `/org/gnome/shell/extensions/gsconnect/device/${device.id}/`, - }); - - // Infobar - this.device.bind_property( - 'paired', - this.infobar, - 'reveal-child', - (GObject.BindingFlags.SYNC_CREATE | - GObject.BindingFlags.INVERT_BOOLEAN) - ); - - this._setupActions(); - - // Settings Pages - this._sharingSettings(); - this._batterySettings(); - this._runcommandSettings(); - this._notificationSettings(); - this._telephonySettings(); - // -------------------------- - this._keybindingSettings(); - this._advancedSettings(); - - // Separate plugins and other settings - this.sidebar.set_header_func((row, before) => { - if (row.get_name() === 'shortcuts') - row.set_header(new Gtk.Separator({visible: true})); - }); - } - - get menu() { - if (this._menu === undefined) { - this._menu = this.device_menu; - this._menu.prepend_section(null, this.device.menu); - this.insert_action_group('device', this.device.action_group); - } - - return this._menu; - } - - get_incoming_supported(type) { - const incoming = this.settings.get_strv('incoming-capabilities'); - return incoming.includes(`kdeconnect.${type}`); - } - - get_outgoing_supported(type) { - const outgoing = this.settings.get_strv('outgoing-capabilities'); - return outgoing.includes(`kdeconnect.${type}`); - } - - _onKeynavFailed(widget, direction) { - if (direction === Gtk.DirectionType.UP && widget.prev) - widget.prev.child_focus(direction); - - else if (direction === Gtk.DirectionType.DOWN && widget.next) - widget.next.child_focus(direction); - - return true; - } - - _onSwitcherRowSelected(box, row) { - this.stack.set_visible_child_name(row.get_name()); - } - - _onSectionRowActivated(box, row) { - if (row.widget !== undefined) - row.widget.active = !row.widget.active; - } - - _onToggleRowActivated(box, row) { - const widget = row.get_child().get_child_at(1, 0); - widget.active = !widget.active; - } - - _onEncryptionInfo() { - const dialog = new Gtk.MessageDialog({ - buttons: Gtk.ButtonsType.OK, - text: _('Encryption Info'), - secondary_text: this.device.encryption_info, - modal: true, - transient_for: this.get_toplevel(), - }); - dialog.connect('response', (dialog) => dialog.destroy()); - dialog.present(); - } - - _deviceAction(action, parameter) { - this.action_group.activate_action(action.name, parameter); - } - - dispose() { - if (this._commandEditor !== undefined) - this._commandEditor.destroy(); - - // Device signals - this.device.action_group.disconnect(this._actionAddedId); - this.device.action_group.disconnect(this._actionRemovedId); - - // GSettings - for (const settings of Object.values(this._pluginSettings)) - settings.run_dispose(); - - this.settings.disconnect(this._keybindingsId); - this.settings.disconnect(this._disabledPluginsId); - this.settings.disconnect(this._supportedPluginsId); - this.settings.run_dispose(); - } - - pluginSettings(name) { - if (this._pluginSettings === undefined) - this._pluginSettings = {}; - - if (!this._pluginSettings.hasOwnProperty(name)) { - const meta = plugins[name].Metadata; - - this._pluginSettings[name] = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup(meta.id, -1), - path: `${this.settings.path}plugin/${name}/`, - }); - } - - return this._pluginSettings[name]; - } - - _setupActions() { - this.actions = new Gio.SimpleActionGroup(); - this.insert_action_group('settings', this.actions); - - let settings = this.pluginSettings('battery'); - this.actions.add_action(settings.create_action('send-statistics')); - this.actions.add_action(settings.create_action('low-battery-notification')); - this.actions.add_action(settings.create_action('custom-battery-notification')); - this.actions.add_action(settings.create_action('custom-battery-notification-value')); - this.actions.add_action(settings.create_action('full-battery-notification')); - - settings = this.pluginSettings('clipboard'); - this.actions.add_action(settings.create_action('send-content')); - this.actions.add_action(settings.create_action('receive-content')); - - settings = this.pluginSettings('contacts'); - this.actions.add_action(settings.create_action('contacts-source')); - - settings = this.pluginSettings('mousepad'); - this.actions.add_action(settings.create_action('share-control')); - - settings = this.pluginSettings('mpris'); - this.actions.add_action(settings.create_action('share-players')); - - settings = this.pluginSettings('notification'); - this.actions.add_action(settings.create_action('send-notifications')); - this.actions.add_action(settings.create_action('send-active')); - - settings = this.pluginSettings('sftp'); - this.actions.add_action(settings.create_action('automount')); - - settings = this.pluginSettings('share'); - this.actions.add_action(settings.create_action('receive-files')); - - settings = this.pluginSettings('sms'); - this.actions.add_action(settings.create_action('legacy-sms')); - - settings = this.pluginSettings('systemvolume'); - this.actions.add_action(settings.create_action('share-sinks')); - - settings = this.pluginSettings('telephony'); - this.actions.add_action(settings.create_action('ringing-volume')); - this.actions.add_action(settings.create_action('ringing-pause')); - this.actions.add_action(settings.create_action('talking-volume')); - this.actions.add_action(settings.create_action('talking-pause')); - this.actions.add_action(settings.create_action('talking-microphone')); - - // Pair Actions - const encryption_info = new Gio.SimpleAction({name: 'encryption-info'}); - encryption_info.connect('activate', this._onEncryptionInfo.bind(this)); - this.actions.add_action(encryption_info); - - const status_pair = new Gio.SimpleAction({name: 'pair'}); - status_pair.connect('activate', this._deviceAction.bind(this.device)); - this.settings.bind('paired', status_pair, 'enabled', 16); - this.actions.add_action(status_pair); - - const status_unpair = new Gio.SimpleAction({name: 'unpair'}); - status_unpair.connect('activate', this._deviceAction.bind(this.device)); - this.settings.bind('paired', status_unpair, 'enabled', 0); - this.actions.add_action(status_unpair); - } - - /** - * Sharing Settings - */ - _sharingSettings() { - // Share Plugin - const settings = this.pluginSettings('share'); - - settings.connect( - 'changed::receive-directory', - this._onReceiveDirectoryChanged.bind(this) - ); - this._onReceiveDirectoryChanged(settings, 'receive-directory'); - - // Visibility - this.desktop_list.foreach(row => { - const name = row.get_name(); - row.visible = this.get_outgoing_supported(`${name}.request`); - }); - - // Separators & Sorting - this.desktop_list.set_header_func(rowSeparators); - - this.desktop_list.set_sort_func((row1, row2) => { - row1 = row1.get_child().get_child_at(0, 0); - row2 = row2.get_child().get_child_at(0, 0); - return row1.label.localeCompare(row2.label); - }); - this.share_list.set_header_func(rowSeparators); - - // Scroll with keyboard focus - const sharing_box = this.sharing_page.get_child().get_child(); - sharing_box.set_focus_vadjustment(this.sharing_page.vadjustment); - - // Continue focus chain between lists - this.desktop_list.next = this.share_list; - this.share_list.prev = this.desktop_list; - } - - _onReceiveDirectoryChanged(settings, key) { - let receiveDir = settings.get_string(key); - - if (receiveDir.length === 0) { - receiveDir = GLib.get_user_special_dir( - GLib.UserDirectory.DIRECTORY_DOWNLOAD - ); - - // Account for some corner cases with a fallback - const homeDir = GLib.get_home_dir(); - - if (!receiveDir || receiveDir === homeDir) - receiveDir = GLib.build_filenamev([homeDir, 'Downloads']); - - settings.set_string(key, receiveDir); - } - - if (this.receive_directory.get_filename() !== receiveDir) - this.receive_directory.set_filename(receiveDir); - } - - _onReceiveDirectorySet(button) { - const settings = this.pluginSettings('share'); - const receiveDir = settings.get_string('receive-directory'); - const filename = button.get_filename(); - - if (filename !== receiveDir) - settings.set_string('receive-directory', filename); - } - - /** - * Battery Settings - */ - async _batterySettings() { - try { - this.battery_device_list.set_header_func(rowSeparators); - this.battery_system_list.set_header_func(rowSeparators); - const settings = this.pluginSettings('battery'); - const oldLevel = settings.get_uint('custom-battery-notification-value'); - this.battery_custom_notification_value.set_value(oldLevel); - - // If the device can't handle statistics we're done - if (!this.get_incoming_supported('battery')) { - this.battery_system_label.visible = false; - this.battery_system.visible = false; - return; - } - - // Check UPower for a battery - const hasBattery = await new Promise((resolve, reject) => { - Gio.DBus.system.call( - 'org.freedesktop.UPower', - '/org/freedesktop/UPower/devices/DisplayDevice', - 'org.freedesktop.DBus.Properties', - 'Get', - new GLib.Variant('(ss)', [ - 'org.freedesktop.UPower.Device', - 'IsPresent', - ]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (connection, res) => { - try { - const variant = connection.call_finish(res); - const value = variant.deepUnpack()[0]; - const isPresent = value.get_boolean(); - - resolve(isPresent); - } catch (e) { - resolve(false); - } - } - ); - }); - - this.battery_system_label.visible = hasBattery; - this.battery_system.visible = hasBattery; - } catch (e) { - this.battery_system_label.visible = false; - this.battery_system.visible = false; - } - } - - _setCustomChargeLevel(spin) { - const settings = this.pluginSettings('battery'); - settings.set_uint('custom-battery-notification-value', spin.get_value_as_int()); - } - - /** - * RunCommand Page - */ - _runcommandSettings() { - // Scroll with keyboard focus - const runcommand_box = this.runcommand_page.get_child().get_child(); - runcommand_box.set_focus_vadjustment(this.runcommand_page.vadjustment); - - // Local Command List - const settings = this.pluginSettings('runcommand'); - this._commands = settings.get_value('command-list').recursiveUnpack(); - - this.command_list.set_sort_func(this._sortCommands); - this.command_list.set_header_func(rowSeparators); - - for (const uuid of Object.keys(this._commands)) - this._insertCommand(uuid); - } - - _sortCommands(row1, row2) { - if (!row1.title || !row2.title) - return 1; - - return row1.title.localeCompare(row2.title); - } - - _insertCommand(uuid) { - const row = new SectionRow({ - title: this._commands[uuid].name, - subtitle: this._commands[uuid].command, - activatable: false, - }); - row.set_name(uuid); - row.subtitle_label.ellipsize = Pango.EllipsizeMode.MIDDLE; - - const editButton = new Gtk.Button({ - image: new Gtk.Image({ - icon_name: 'document-edit-symbolic', - pixel_size: 16, - visible: true, - }), - tooltip_text: _('Edit'), - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }); - editButton.connect('clicked', this._onEditCommand.bind(this)); - editButton.get_accessible().set_name(_('Edit')); - row.get_child().attach(editButton, 2, 0, 1, 2); - - const deleteButton = new Gtk.Button({ - image: new Gtk.Image({ - icon_name: 'edit-delete-symbolic', - pixel_size: 16, - visible: true, - }), - tooltip_text: _('Remove'), - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }); - deleteButton.connect('clicked', this._onDeleteCommand.bind(this)); - deleteButton.get_accessible().set_name(_('Remove')); - row.get_child().attach(deleteButton, 3, 0, 1, 2); - - this.command_list.add(row); - } - - _onEditCommand(widget) { - if (this._commandEditor === undefined) { - this._commandEditor = new CommandEditor({ - modal: true, - transient_for: this.get_toplevel(), - use_header_bar: true, - }); - - this._commandEditor.connect( - 'response', - this._onSaveCommand.bind(this) - ); - - this._commandEditor.resize(1, 1); - } - - if (widget instanceof Gtk.Button) { - const row = widget.get_ancestor(Gtk.ListBoxRow.$gtype); - const uuid = row.get_name(); - - this._commandEditor.uuid = uuid; - this._commandEditor.command_name = this._commands[uuid].name; - this._commandEditor.command_line = this._commands[uuid].command; - } else { - this._commandEditor.uuid = GLib.uuid_string_random(); - this._commandEditor.command_name = ''; - this._commandEditor.command_line = ''; - } - - this._commandEditor.present(); - } - - _storeCommands() { - const variant = {}; - - for (const [uuid, command] of Object.entries(this._commands)) - variant[uuid] = new GLib.Variant('a{ss}', command); - - this.pluginSettings('runcommand').set_value( - 'command-list', - new GLib.Variant('a{sv}', variant) - ); - } - - _onDeleteCommand(button) { - const row = button.get_ancestor(Gtk.ListBoxRow.$gtype); - delete this._commands[row.get_name()]; - row.destroy(); - - this._storeCommands(); - } - - _onSaveCommand(dialog, response_id) { - if (response_id === Gtk.ResponseType.ACCEPT) { - this._commands[dialog.uuid] = { - name: dialog.command_name, - command: dialog.command_line, - }; - - this._storeCommands(); - - // - let row = null; - - for (const child of this.command_list.get_children()) { - if (child.get_name() === dialog.uuid) { - row = child; - break; - } - } - - if (row === null) { - this._insertCommand(dialog.uuid); - } else { - row.set_name(dialog.uuid); - row.title = dialog.command_name; - row.subtitle = dialog.command_line; - } - } - - dialog.hide(); - } - - /** - * Notification Settings - */ - _notificationSettings() { - const settings = this.pluginSettings('notification'); - - settings.bind( - 'send-notifications', - this.notification_apps, - 'sensitive', - Gio.SettingsBindFlags.DEFAULT - ); - - // Separators & Sorting - this.notification_list.set_header_func(rowSeparators); - - // Scroll with keyboard focus - const notification_box = this.notification_page.get_child().get_child(); - notification_box.set_focus_vadjustment(this.notification_page.vadjustment); - - // Continue focus chain between lists - this.notification_list.next = this.notification_apps; - this.notification_apps.prev = this.notification_list; - - this.notification_apps.set_sort_func(titleSortFunc); - this.notification_apps.set_header_func(rowSeparators); - - this._populateApplications(settings); - } - - _toggleNotification(widget) { - try { - const row = widget.get_ancestor(Gtk.ListBoxRow.$gtype); - const settings = this.pluginSettings('notification'); - let applications = {}; - - try { - applications = JSON.parse(settings.get_string('applications')); - } catch (e) { - applications = {}; - } - - applications[row.title].enabled = !applications[row.title].enabled; - row.widget.state = applications[row.title].enabled; - settings.set_string('applications', JSON.stringify(applications)); - - } catch (e) { - logError(e); - } - } - - - - _populateApplications(settings) { - const applications = this._queryApplications(settings); - - for (const name in applications) { - const row = new SectionRow({ - gicon: Gio.Icon.new_for_string(applications[name].iconName), - title: name, - height_request: 48, - widget: new Gtk.Switch({ - state: applications[name].enabled, - margin_start: 12, - margin_end: 12, - halign: Gtk.Align.END, - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }), - }); - - row.widget.connect('notify::active', this._toggleNotification.bind(this)); - this.notification_apps.add(row); - } - } - - _queryApplications(settings) { - let applications = {}; - - try { - applications = JSON.parse(settings.get_string('applications')); - } catch (e) { - applications = {}; - } - - // Scan applications that statically declare to show notifications - const ignoreId = 'org.gnome.Shell.Extensions.GSConnect.desktop'; - - for (const appInfo of Gio.AppInfo.get_all()) { - if (appInfo.get_id() === ignoreId) - continue; - - if (!appInfo.get_boolean('X-GNOME-UsesNotifications')) - continue; - - const appName = appInfo.get_name(); - - if (appName === null || applications.hasOwnProperty(appName)) - continue; - - let icon = appInfo.get_icon(); - icon = (icon) ? icon.to_string() : 'application-x-executable'; - - applications[appName] = { - iconName: icon, - enabled: true, - }; - } - - settings.set_string('applications', JSON.stringify(applications)); - - return applications; - } - - /** - * Telephony Settings - */ - _telephonySettings() { - // Continue focus chain between lists - this.ringing_list.next = this.talking_list; - this.talking_list.prev = this.ringing_list; - - this.ringing_list.set_header_func(rowSeparators); - this.talking_list.set_header_func(rowSeparators); - } - - /** - * Keyboard Shortcuts - */ - _keybindingSettings() { - // Scroll with keyboard focus - const shortcuts_box = this.shortcuts_page.get_child().get_child(); - shortcuts_box.set_focus_vadjustment(this.shortcuts_page.vadjustment); - - // Filter & Sort - this.shortcuts_actions_list.set_filter_func(this._filterPluginKeybindings.bind(this)); - this.shortcuts_actions_list.set_header_func(rowSeparators); - this.shortcuts_actions_list.set_sort_func(titleSortFunc); - - // Init - for (const name in DEVICE_SHORTCUTS) - this._addPluginKeybinding(name); - - this._setPluginKeybindings(); - - // Watch for GAction and Keybinding changes - this._actionAddedId = this.device.action_group.connect( - 'action-added', - () => this.shortcuts_actions_list.invalidate_filter() - ); - this._actionRemovedId = this.device.action_group.connect( - 'action-removed', - () => this.shortcuts_actions_list.invalidate_filter() - ); - this._keybindingsId = this.settings.connect( - 'changed::keybindings', - this._setPluginKeybindings.bind(this) - ); - } - - _addPluginKeybinding(name) { - const [icon_name, label] = DEVICE_SHORTCUTS[name]; - - const widget = new Gtk.Label({ - label: _('Disabled'), - visible: true, - }); - widget.get_style_context().add_class('dim-label'); - - const row = new SectionRow({ - height_request: 48, - icon_name: icon_name, - title: label, - widget: widget, - }); - row.icon_image.pixel_size = 16; - row.action = name; - this.shortcuts_actions_list.add(row); - } - - _filterPluginKeybindings(row) { - return this.device.action_group.has_action(row.action); - } - - _setPluginKeybindings() { - const keybindings = this.settings.get_value('keybindings').deepUnpack(); - - this.shortcuts_actions_list.foreach(row => { - if (keybindings[row.action]) { - const accel = Gtk.accelerator_parse(keybindings[row.action]); - row.widget.label = Gtk.accelerator_get_label(...accel); - } else { - row.widget.label = _('Disabled'); - } - }); - } - - _onResetActionShortcuts(button) { - const keybindings = this.settings.get_value('keybindings').deepUnpack(); - - for (const action in keybindings) { - // Don't reset remote command shortcuts - if (!action.includes('::')) - delete keybindings[action]; - } - - this.settings.set_value( - 'keybindings', - new GLib.Variant('a{ss}', keybindings) - ); - } - - async _onShortcutRowActivated(box, row) { - try { - const keybindings = this.settings.get_value('keybindings').deepUnpack(); - let accel = keybindings[row.action] || null; - - accel = await Keybindings.getAccelerator(row.title, accel); - - if (accel) - keybindings[row.action] = accel; - else - delete keybindings[row.action]; - - this.settings.set_value( - 'keybindings', - new GLib.Variant('a{ss}', keybindings) - ); - } catch (e) { - logError(e); - } - } - - /** - * Advanced Page - */ - _advancedSettings() { - // Scroll with keyboard focus - const advanced_box = this.advanced_page.get_child().get_child(); - advanced_box.set_focus_vadjustment(this.advanced_page.vadjustment); - - // Sort & Separate - this.plugin_list.set_header_func(rowSeparators); - this.plugin_list.set_sort_func(titleSortFunc); - this.experimental_list.set_header_func(rowSeparators); - - // Continue focus chain between lists - this.plugin_list.next = this.experimental_list; - this.experimental_list.prev = this.plugin_list; - - this._disabledPluginsId = this.settings.connect( - 'changed::disabled-plugins', - this._onPluginsChanged.bind(this) - ); - this._supportedPluginsId = this.settings.connect( - 'changed::supported-plugins', - this._onPluginsChanged.bind(this) - ); - this._onPluginsChanged(this.settings, null); - - for (const name of DEVICE_PLUGINS) - this._addPlugin(name); - } - - _onPluginsChanged(settings, key) { - if (key === 'disabled-plugins' || this._disabledPlugins === undefined) - this._disabledPlugins = settings.get_strv('disabled-plugins'); - - if (key === 'supported-plugins' || this._supportedPlugins === undefined) - this._supportedPlugins = settings.get_strv('supported-plugins'); - - this._enabledPlugins = this._supportedPlugins.filter(name => { - return !this._disabledPlugins.includes(name); - }); - - if (key !== null) - this._updatePlugins(); - } - - _addPlugin(name) { - const plugin = plugins[name]; - - const row = new SectionRow({ - height_request: 48, - title: plugin.Metadata.label, - subtitle: plugin.Metadata.description || '', - visible: this._supportedPlugins.includes(name), - widget: new Gtk.Switch({ - active: this._enabledPlugins.includes(name), - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }), - }); - row.widget.connect('notify::active', this._togglePlugin.bind(this)); - row.set_name(name); - - if (this.hasOwnProperty(name)) - this[name].visible = row.widget.active; - - this.plugin_list.add(row); - } - - _updatePlugins(settings, key) { - for (const row of this.plugin_list.get_children()) { - const name = row.get_name(); - - row.visible = this._supportedPlugins.includes(name); - row.widget.active = this._enabledPlugins.includes(name); - - if (this.hasOwnProperty(name)) - this[name].visible = row.widget.active; - } - } - - _togglePlugin(widget) { - try { - const name = widget.get_ancestor(Gtk.ListBoxRow.$gtype).get_name(); - const index = this._disabledPlugins.indexOf(name); - - // Either add or remove the plugin from the disabled list - if (index > -1) - this._disabledPlugins.splice(index, 1); - else - this._disabledPlugins.push(name); - - this.settings.set_strv('disabled-plugins', this._disabledPlugins); - } catch (e) { - logError(e); - } - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/init.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/init.js deleted file mode 100755 index 038f60e7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/init.js +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GLib from 'gi://GLib'; - -import setup, {setupGettext} from '../utils/setup.js'; - - -// Bootstrap -setup(GLib.path_get_dirname(GLib.path_get_dirname(GLib.filename_from_uri(import.meta.url)[0]))); -setupGettext(); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/keybindings.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/keybindings.js deleted file mode 100755 index be80dfea..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/keybindings.js +++ /dev/null @@ -1,314 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - - -/* - * A list of modifier keysyms we ignore - */ -const _MODIFIERS = [ - Gdk.KEY_Alt_L, - Gdk.KEY_Alt_R, - Gdk.KEY_Caps_Lock, - Gdk.KEY_Control_L, - Gdk.KEY_Control_R, - Gdk.KEY_Meta_L, - Gdk.KEY_Meta_R, - Gdk.KEY_Num_Lock, - Gdk.KEY_Shift_L, - Gdk.KEY_Shift_R, - Gdk.KEY_Super_L, - Gdk.KEY_Super_R, -]; - -/** - * Response enum for ShortcutChooserDialog - */ -export const ResponseType = { - CANCEL: Gtk.ResponseType.CANCEL, - SET: Gtk.ResponseType.APPLY, - UNSET: 2, -}; - - -/** - * A simplified version of the shortcut editor from GNOME Control Center - */ -export const ShortcutChooserDialog = GObject.registerClass({ - GTypeName: 'GSConnectPreferencesShortcutEditor', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-shortcut-editor.ui', - Children: [ - 'cancel-button', 'set-button', - 'stack', 'summary-label', - 'shortcut-label', 'conflict-label', - ], -}, class ShortcutChooserDialog extends Gtk.Dialog { - - _init(params) { - super._init({ - transient_for: Gio.Application.get_default().get_active_window(), - use_header_bar: true, - }); - - this._seat = Gdk.Display.get_default().get_default_seat(); - - // Current accelerator or %null - this.accelerator = params.accelerator; - - // TRANSLATORS: Summary of a keyboard shortcut function - // Example: Enter a new shortcut to change Messaging - this.summary = _('Enter a new shortcut to change %s').format( - params.summary - ); - } - - get accelerator() { - return this.shortcut_label.accelerator; - } - - set accelerator(value) { - this.shortcut_label.accelerator = value; - } - - get summary() { - return this.summary_label.label; - } - - set summary(value) { - this.summary_label.label = value; - } - - vfunc_key_press_event(event) { - let keyvalLower = Gdk.keyval_to_lower(event.keyval); - let realMask = event.state & Gtk.accelerator_get_default_mod_mask(); - - // TODO: Critical: 'WIDGET_REALIZED_FOR_EVENT (widget, event)' failed - if (_MODIFIERS.includes(keyvalLower)) - return true; - - // Normalize Tab - if (keyvalLower === Gdk.KEY_ISO_Left_Tab) - keyvalLower = Gdk.KEY_Tab; - - // Put shift back if it changed the case of the key, not otherwise. - if (keyvalLower !== event.keyval) - realMask |= Gdk.ModifierType.SHIFT_MASK; - - // HACK: we don't want to use SysRq as a keybinding (but we do want - // Alt+Print), so we avoid translation from Alt+Print to SysRq - if (keyvalLower === Gdk.KEY_Sys_Req && (realMask & Gdk.ModifierType.MOD1_MASK) !== 0) - keyvalLower = Gdk.KEY_Print; - - // A single Escape press cancels the editing - if (realMask === 0 && keyvalLower === Gdk.KEY_Escape) { - this.response(ResponseType.CANCEL); - return false; - } - - // Backspace disables the current shortcut - if (realMask === 0 && keyvalLower === Gdk.KEY_BackSpace) { - this.response(ResponseType.UNSET); - return false; - } - - // CapsLock isn't supported as a keybinding modifier, so keep it from - // confusing us - realMask &= ~Gdk.ModifierType.LOCK_MASK; - - if (keyvalLower !== 0 && realMask !== 0) { - this._ungrab(); - - // Set the accelerator property/label - this.accelerator = Gtk.accelerator_name(keyvalLower, realMask); - - // TRANSLATORS: When a keyboard shortcut is unavailable - // Example: [Ctrl]+[S] is already being used - this.conflict_label.label = _('%s is already being used').format( - Gtk.accelerator_get_label(keyvalLower, realMask) - ); - - // Show Cancel button and switch to confirm/conflict page - this.cancel_button.visible = true; - this.stack.visible_child_name = 'confirm'; - - this._check(); - } - - return true; - } - - async _check() { - try { - const available = await checkAccelerator(this.accelerator); - this.set_button.visible = available; - this.conflict_label.visible = !available; - } catch (e) { - logError(e); - this.response(ResponseType.CANCEL); - } - } - - _grab() { - const success = this._seat.grab( - this.get_window(), - Gdk.SeatCapabilities.KEYBOARD, - true, // owner_events - null, // cursor - null, // event - null - ); - - if (success !== Gdk.GrabStatus.SUCCESS) - return this.response(ResponseType.CANCEL); - - if (!this._seat.get_keyboard() && !this._seat.get_pointer()) - return this.response(ResponseType.CANCEL); - - this.grab_add(); - } - - _ungrab() { - this._seat.ungrab(); - this.grab_remove(); - } - - // Override to use our own ungrab process - response(response_id) { - this.hide(); - this._ungrab(); - - return super.response(response_id); - } - - // Override with a non-blocking version of Gtk.Dialog.run() - run() { - this.show(); - - // Wait a bit before attempting grab - GLib.timeout_add(GLib.PRIORITY_DEFAULT, 100, () => { - this._grab(); - return GLib.SOURCE_REMOVE; - }); - } -}); - - -/** - * Check the availability of an accelerator using GNOME Shell's DBus interface. - * - * @param {string} accelerator - An accelerator - * @param {number} [modeFlags] - Mode Flags - * @param {number} [grabFlags] - Grab Flags - * @param {boolean} %true if available, %false on error or unavailable - */ -export async function checkAccelerator(accelerator, modeFlags = 0, grabFlags = 0) { - try { - let result = false; - - // Try to grab the accelerator - const action = await new Promise((resolve, reject) => { - Gio.DBus.session.call( - 'org.gnome.Shell', - '/org/gnome/Shell', - 'org.gnome.Shell', - 'GrabAccelerator', - new GLib.Variant('(suu)', [accelerator, modeFlags, grabFlags]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (connection, res) => { - try { - res = connection.call_finish(res); - resolve(res.deepUnpack()[0]); - } catch (e) { - reject(e); - } - } - ); - }); - - // If successful, use the result of ungrabbing as our return - if (action !== 0) { - result = await new Promise((resolve, reject) => { - Gio.DBus.session.call( - 'org.gnome.Shell', - '/org/gnome/Shell', - 'org.gnome.Shell', - 'UngrabAccelerator', - new GLib.Variant('(u)', [action]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (connection, res) => { - try { - res = connection.call_finish(res); - resolve(res.deepUnpack()[0]); - } catch (e) { - reject(e); - } - } - ); - }); - } - - return result; - } catch (e) { - logError(e); - return false; - } -} - - -/** - * Show a dialog to get a keyboard shortcut from a user. - * - * @param {string} summary - A description of the keybinding's function - * @param {string} accelerator - An accelerator as taken by Gtk.ShortcutLabel - * @return {string} An accelerator or %null if it should be unset. - */ -export async function getAccelerator(summary, accelerator = null) { - try { - const dialog = new ShortcutChooserDialog({ - summary: summary, - accelerator: accelerator, - }); - - accelerator = await new Promise((resolve, reject) => { - dialog.connect('response', (dialog, response) => { - switch (response) { - case ResponseType.SET: - accelerator = dialog.accelerator; - break; - - case ResponseType.UNSET: - accelerator = null; - break; - - case ResponseType.CANCEL: - // leave the accelerator as passed in - break; - } - - dialog.destroy(); - - resolve(accelerator); - }); - - dialog.run(); - }); - - return accelerator; - } catch (e) { - logError(e); - return accelerator; - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/service.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/service.js deleted file mode 100755 index e258f225..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/preferences/service.js +++ /dev/null @@ -1,648 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import system from 'system'; - -import Config from '../config.js'; -import {Panel, rowSeparators} from './device.js'; -import {Service} from '../utils/remote.js'; - - -/* - * Header for support logs - */ -const LOG_HEADER = new GLib.Bytes(` -GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'}) -GJS: ${system.version} -Session: ${GLib.getenv('XDG_SESSION_TYPE')} -OS: ${GLib.get_os_info('PRETTY_NAME')} --------------------------------------------------------------------------------- -`); - - -/** - * Generate a support log. - * - * @param {string} time - Start time as a string (24-hour notation) - */ -async function generateSupportLog(time) { - try { - const [file, stream] = Gio.File.new_tmp('gsconnect.XXXXXX'); - const logFile = stream.get_output_stream(); - - await new Promise((resolve, reject) => { - logFile.write_bytes_async(LOG_HEADER, 0, null, (file, res) => { - try { - resolve(file.write_bytes_finish(res)); - } catch (e) { - reject(e); - } - }); - }); - - // FIXME: BSD??? - const proc = new Gio.Subprocess({ - flags: (Gio.SubprocessFlags.STDOUT_PIPE | - Gio.SubprocessFlags.STDERR_MERGE), - argv: ['journalctl', '--no-host', '--since', time], - }); - proc.init(null); - - logFile.splice_async( - proc.get_stdout_pipe(), - Gio.OutputStreamSpliceFlags.CLOSE_TARGET, - GLib.PRIORITY_DEFAULT, - null, - (source, res) => { - try { - source.splice_finish(res); - } catch (e) { - logError(e); - } - } - ); - - await new Promise((resolve, reject) => { - proc.wait_check_async(null, (proc, res) => { - try { - resolve(proc.wait_finish(res)); - } catch (e) { - reject(e); - } - }); - }); - - const uri = file.get_uri(); - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } catch (e) { - logError(e); - } -} - - -/** - * "Connect to..." Dialog - */ -const ConnectDialog = GObject.registerClass({ - GTypeName: 'GSConnectConnectDialog', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/connect-dialog.ui', - Children: [ - 'cancel-button', 'connect-button', - 'lan-grid', 'lan-ip', 'lan-port', - ], -}, class ConnectDialog extends Gtk.Dialog { - - _init(params = {}) { - super._init(Object.assign({ - use_header_bar: true, - }, params)); - } - - vfunc_response(response_id) { - if (response_id === Gtk.ResponseType.OK) { - try { - let address; - - // Lan host/port entered - if (this.lan_ip.text) { - const host = this.lan_ip.text; - const port = this.lan_port.value; - address = GLib.Variant.new_string(`lan://${host}:${port}`); - } else { - return false; - } - - this.application.activate_action('connect', address); - } catch (e) { - logError(e); - } - } - - this.destroy(); - return false; - } -}); - - -export const Window = GObject.registerClass({ - GTypeName: 'GSConnectPreferencesWindow', - Properties: { - 'display-mode': GObject.ParamSpec.string( - 'display-mode', - 'Display Mode', - 'Display devices in either the Panel or User Menu', - GObject.ParamFlags.READWRITE, - null - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/preferences-window.ui', - Children: [ - // HeaderBar - 'headerbar', 'infobar', 'stack', - 'service-menu', 'service-edit', 'refresh-button', - 'device-menu', 'prev-button', - - // Popover - 'rename-popover', 'rename', 'rename-label', 'rename-entry', 'rename-submit', - - // Focus Box - 'service-window', 'service-box', - - // Device List - 'device-list', 'device-list-spinner', 'device-list-placeholder', - ], -}, class PreferencesWindow extends Gtk.ApplicationWindow { - - _init(params = {}) { - super._init(params); - - // Service Settings - this.settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect', - true - ), - }); - - // Service Proxy - this.service = new Service(); - - this._deviceAddedId = this.service.connect( - 'device-added', - this._onDeviceAdded.bind(this) - ); - - this._deviceRemovedId = this.service.connect( - 'device-removed', - this._onDeviceRemoved.bind(this) - ); - - this._serviceChangedId = this.service.connect( - 'notify::active', - this._onServiceChanged.bind(this) - ); - - // HeaderBar (Service Name) - this.headerbar.title = this.settings.get_string('name'); - this.rename_entry.text = this.headerbar.title; - - // Scroll with keyboard focus - this.service_box.set_focus_vadjustment(this.service_window.vadjustment); - - // Device List - this.device_list.set_header_func(rowSeparators); - - // Discoverable InfoBar - this.settings.bind( - 'discoverable', - this.infobar, - 'reveal-child', - Gio.SettingsBindFlags.INVERT_BOOLEAN - ); - this.add_action(this.settings.create_action('discoverable')); - - // Application Menu - this._initMenu(); - - // Setting: Keep Alive When Locked - this.add_action(this.settings.create_action('keep-alive-when-locked')); - - // Broadcast automatically every 5 seconds if there are no devices yet - this._refreshSource = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, - 5, - this._refresh.bind(this) - ); - - // Restore window size/maximized/position - this._restoreGeometry(); - - // Prime the service - this._initService(); - } - - get display_mode() { - if (this.settings.get_boolean('show-indicators')) - return 'panel'; - - return 'user-menu'; - } - - set display_mode(mode) { - this.settings.set_boolean('show-indicators', (mode === 'panel')); - } - - vfunc_delete_event(event) { - if (this.service) { - this.service.disconnect(this._deviceAddedId); - this.service.disconnect(this._deviceRemovedId); - this.service.disconnect(this._serviceChangedId); - this.service.destroy(); - this.service = null; - } - - this._saveGeometry(); - GLib.source_remove(this._refreshSource); - - return false; - } - - async _initService() { - try { - this.refresh_button.grab_focus(); - - this._onServiceChanged(this.service, null); - await this.service.reload(); - } catch (e) { - logError(e, 'GSConnect'); - } - } - - _initMenu() { - // Panel/User Menu mode - const displayMode = new Gio.PropertyAction({ - name: 'display-mode', - property_name: 'display-mode', - object: this, - }); - this.add_action(displayMode); - - // About Dialog - const aboutDialog = new Gio.SimpleAction({name: 'about'}); - aboutDialog.connect('activate', this._aboutDialog.bind(this)); - this.add_action(aboutDialog); - - // "Connect to..." Dialog - const connectDialog = new Gio.SimpleAction({name: 'connect'}); - connectDialog.connect('activate', this._connectDialog.bind(this)); - this.add_action(connectDialog); - - // "Generate Support Log" GAction - const generateSupportLog = new Gio.SimpleAction({name: 'support-log'}); - generateSupportLog.connect('activate', this._generateSupportLog.bind(this)); - this.add_action(generateSupportLog); - - // "Help" GAction - const help = new Gio.SimpleAction({name: 'help'}); - help.connect('activate', this._help); - this.add_action(help); - } - - _refresh() { - if (this.service.active && this.device_list.get_children().length < 1) { - this.device_list_spinner.active = true; - this.service.activate_action('refresh', null); - } else { - this.device_list_spinner.active = false; - } - - return GLib.SOURCE_CONTINUE; - } - - /* - * Window State - */ - _restoreGeometry() { - this._windowState = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect.WindowState', - true - ), - path: '/org/gnome/shell/extensions/gsconnect/preferences/', - }); - - // Size - const [width, height] = this._windowState.get_value('window-size').deepUnpack(); - - if (width && height) - this.set_default_size(width, height); - - // Maximized State - if (this._windowState.get_boolean('window-maximized')) - this.maximize(); - } - - _saveGeometry() { - const state = this.get_window().get_state(); - - // Maximized State - const maximized = (state & Gdk.WindowState.MAXIMIZED); - this._windowState.set_boolean('window-maximized', maximized); - - // Leave the size at the value before maximizing - if (maximized || (state & Gdk.WindowState.FULLSCREEN)) - return; - - // Size - const size = this.get_size(); - this._windowState.set_value('window-size', new GLib.Variant('(ii)', size)); - } - - /** - * About Dialog - */ - _aboutDialog() { - if (this._about === undefined) { - this._about = new Gtk.AboutDialog({ - application: Gio.Application.get_default(), - authors: [ - 'Andy Holmes ', - 'Bertrand Lacoste ', - 'Frank Dana ', - ], - comments: _('A complete KDE Connect implementation for GNOME'), - logo: GdkPixbuf.Pixbuf.new_from_resource_at_scale( - '/org/gnome/Shell/Extensions/GSConnect/icons/org.gnome.Shell.Extensions.GSConnect.svg', - 128, - 128, - true - ), - program_name: 'GSConnect', - // TRANSLATORS: eg. 'Translator Name ' - translator_credits: _('translator-credits'), - version: Config.PACKAGE_VERSION.toString(), - website: Config.PACKAGE_URL, - license_type: Gtk.License.GPL_2_0, - modal: true, - transient_for: this, - }); - - // Persist - this._about.connect('response', (dialog) => dialog.hide_on_delete()); - this._about.connect('delete-event', (dialog) => dialog.hide_on_delete()); - } - - this._about.present(); - } - - /** - * Connect to..." Dialog - */ - _connectDialog() { - new ConnectDialog({ - application: Gio.Application.get_default(), - modal: true, - transient_for: this, - }); - } - - /* - * "Generate Support Log" GAction - */ - _generateSupportLog() { - const dialog = new Gtk.MessageDialog({ - text: _('Generate Support Log'), - secondary_text: _('Debug messages are being logged. Take any steps necessary to reproduce a problem then review the log.'), - }); - dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); - dialog.add_button(_('Review Log'), Gtk.ResponseType.OK); - - // Enable debug logging and mark the current time - this.settings.set_boolean('debug', true); - const now = GLib.DateTime.new_now_local().format('%R'); - - dialog.connect('response', (dialog, response_id) => { - // Disable debug logging and destroy the dialog - this.settings.set_boolean('debug', false); - dialog.destroy(); - - // Only generate a log if instructed - if (response_id === Gtk.ResponseType.OK) - generateSupportLog(now); - }); - - dialog.show_all(); - } - - /* - * "Help" GAction - */ - _help(action, parameter) { - const uri = `${Config.PACKAGE_URL}/wiki/Help`; - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } - - /* - * HeaderBar Callbacks - */ - _onPrevious(button, event) { - // HeaderBar (Service) - this.prev_button.visible = false; - this.device_menu.visible = false; - - this.refresh_button.visible = true; - this.service_edit.visible = true; - this.service_menu.visible = true; - - this.headerbar.title = this.settings.get_string('name'); - this.headerbar.subtitle = null; - - // Panel - this.stack.visible_child_name = 'service'; - this._setDeviceMenu(); - } - - _onEditServiceName(button, event) { - this.rename_entry.text = this.headerbar.title; - this.rename_entry.has_focus = true; - } - - _onSetServiceName(widget) { - if (this.rename_entry.text.length) { - this.headerbar.title = this.rename_entry.text; - this.settings.set_string('name', this.rename_entry.text); - } - - this.service_edit.active = false; - this.service_edit.grab_focus(); - } - - /* - * Context Switcher - */ - _getTypeLabel(device) { - switch (device.type) { - case 'laptop': - return _('Laptop'); - case 'phone': - return _('Smartphone'); - case 'tablet': - return _('Tablet'); - case 'tv': - return _('Television'); - default: - return _('Desktop'); - } - } - - _setDeviceMenu(panel = null) { - this.device_menu.insert_action_group('device', null); - this.device_menu.insert_action_group('settings', null); - this.device_menu.set_menu_model(null); - - if (panel === null) - return; - - this.device_menu.insert_action_group('device', panel.device.action_group); - this.device_menu.insert_action_group('settings', panel.actions); - this.device_menu.set_menu_model(panel.menu); - } - - _onDeviceChanged(statusLabel, device, pspec) { - switch (false) { - case device.paired: - statusLabel.label = _('Unpaired'); - break; - - case device.connected: - statusLabel.label = _('Disconnected'); - break; - - default: - statusLabel.label = _('Connected'); - } - } - - _createDeviceRow(device) { - const row = new Gtk.ListBoxRow({ - height_request: 52, - selectable: false, - visible: true, - }); - row.set_name(device.id); - - const grid = new Gtk.Grid({ - column_spacing: 12, - margin_left: 20, - margin_right: 20, - margin_bottom: 8, - margin_top: 8, - visible: true, - }); - row.add(grid); - - const icon = new Gtk.Image({ - gicon: new Gio.ThemedIcon({name: device.icon_name}), - icon_size: Gtk.IconSize.BUTTON, - visible: true, - }); - grid.attach(icon, 0, 0, 1, 1); - - const title = new Gtk.Label({ - halign: Gtk.Align.START, - hexpand: true, - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }); - grid.attach(title, 1, 0, 1, 1); - - const status = new Gtk.Label({ - halign: Gtk.Align.END, - hexpand: true, - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }); - grid.attach(status, 2, 0, 1, 1); - - // Keep name up to date - device.bind_property( - 'name', - title, - 'label', - GObject.BindingFlags.SYNC_CREATE - ); - - // Keep status up to date - device.connect( - 'notify::connected', - this._onDeviceChanged.bind(null, status) - ); - device.connect( - 'notify::paired', - this._onDeviceChanged.bind(null, status) - ); - this._onDeviceChanged(status, device, null); - - return row; - } - - _onDeviceAdded(service, device) { - try { - if (!this.stack.get_child_by_name(device.id)) { - // Add the device preferences - const prefs = new Panel(device); - this.stack.add_titled(prefs, device.id, device.name); - - // Add a row to the device list - prefs.row = this._createDeviceRow(device); - this.device_list.add(prefs.row); - } - } catch (e) { - logError(e); - } - } - - _onDeviceRemoved(service, device) { - try { - const prefs = this.stack.get_child_by_name(device.id); - - if (prefs === null) - return; - - if (prefs === this.stack.get_visible_child()) - this._onPrevious(); - - prefs.row.destroy(); - prefs.row = null; - - prefs.dispose(); - prefs.destroy(); - } catch (e) { - logError(e); - } - } - - _onDeviceSelected(box, row) { - try { - if (row === null) - return this._onPrevious(); - - // Transition the panel - const name = row.get_name(); - const prefs = this.stack.get_child_by_name(name); - - this.stack.visible_child = prefs; - this._setDeviceMenu(prefs); - - // HeaderBar (Device) - this.refresh_button.visible = false; - this.service_edit.visible = false; - this.service_menu.visible = false; - - this.prev_button.visible = true; - this.device_menu.visible = true; - - this.headerbar.title = prefs.device.name; - this.headerbar.subtitle = this._getTypeLabel(prefs.device); - } catch (e) { - logError(e); - } - } - - _onServiceChanged(service, pspec) { - if (this.service.active) - this.device_list_placeholder.label = _('Searching for devices…'); - else - this.device_list_placeholder.label = _('Waiting for service…'); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/prefs.js deleted file mode 100755 index 4a94ca7b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/prefs.js +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Adw from 'gi://Adw'; - -// Bootstrap -import * as Utils from './shell/utils.js'; -import setup from './utils/setup.js'; -import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class GSConnectExtensionPreferences extends ExtensionPreferences { - constructor(metadata) { - super(metadata); - setup(this.path); - Utils.installService(); - } - - fillPreferencesWindow(window) { - const widget = new Adw.PreferencesPage(); - window.add(widget); - - GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - window.close(); - }); - - Gio.Subprocess.new([`${this.path}/gsconnect-preferences`], 0); - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/schemas/gschemas.compiled deleted file mode 100755 index 60e8035b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/schemas/org.gnome.Shell.Extensions.GSConnect.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/schemas/org.gnome.Shell.Extensions.GSConnect.gschema.xml deleted file mode 100755 index 4dfaddb3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/schemas/org.gnome.Shell.Extensions.GSConnect.gschema.xml +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - - true - - - false - - - true - - - true - - - - - "" - - - "" - - - [] - - - false - - - true - - - - - - - (0, 0) - - - false - - - - - - - "" - - - {} - - - ["sms", "ring", "mount", "commands", "share", "keyboard"] - - - "" - - - false - - - "smartphone" - - - [] - - - [] - - - [] - - - [] - - - "" - - - - - - false - - - true - - - false - Enables custom battery notification - - - - 80 - - - false - - - - - false - - - false - - - - - true - - - - - - true - - - - - true - - - - - true - - - true - - - '{}' - - - - - - - , 'restart': <{'name': 'Restart', 'command': 'systemctl reboot'}>, 'logout': <{'name': 'Log Out', 'command': 'gnome-session-quit --logout --no-prompt'}>, 'poweroff': <{'name': 'Power Off', 'command': 'systemctl poweroff'}>, 'suspend': <{'name': 'Suspend', 'command': 'systemctl suspend'}>}]]> - - - - - true - - - - - true - - - "" - - - - - false - - - - - true - - - - - "lower" - - - false - - - "mute" - - - true - - - true - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/backends/lan.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/backends/lan.js deleted file mode 100755 index 758e24bf..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/backends/lan.js +++ /dev/null @@ -1,889 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../../config.js'; -import * as Core from '../core.js'; - -// Retain compatibility with GLib < 2.80, which lacks GioUnix -let GioUnix; -try { - GioUnix = (await import('gi://GioUnix')).default; -} catch (e) { - GioUnix = { - InputStream: Gio.UnixInputStream, - OutputStream: Gio.UnixOutputStream, - }; -} - -/** - * TCP Port Constants - */ -const PROTOCOL_PORT_DEFAULT = 1716; -const PROTOCOL_PORT_MIN = 1716; -const PROTOCOL_PORT_MAX = 1764; -const TRANSFER_MIN = 1739; -const TRANSFER_MAX = 1764; - - -/* - * One-time check for Linux/FreeBSD socket options - */ -export let _LINUX_SOCKETS = true; - -try { - // This should throw on FreeBSD - Gio.Socket.new( - Gio.SocketFamily.IPV4, - Gio.SocketType.STREAM, - Gio.SocketProtocol.TCP - ).get_option(6, 5); -} catch (e) { - _LINUX_SOCKETS = false; -} - - -/** - * Configure a socket connection for the KDE Connect protocol. - * - * @param {Gio.SocketConnection} connection - The connection to configure - */ -export function _configureSocket(connection) { - try { - if (_LINUX_SOCKETS) { - connection.socket.set_option(6, 4, 10); // TCP_KEEPIDLE - connection.socket.set_option(6, 5, 5); // TCP_KEEPINTVL - connection.socket.set_option(6, 6, 3); // TCP_KEEPCNT - - // FreeBSD constants - // https://github.com/freebsd/freebsd/blob/master/sys/netinet/tcp.h#L159 - } else { - connection.socket.set_option(6, 256, 10); // TCP_KEEPIDLE - connection.socket.set_option(6, 512, 5); // TCP_KEEPINTVL - connection.socket.set_option(6, 1024, 3); // TCP_KEEPCNT - } - - // Do this last because an error setting the keepalive options would - // result in a socket that never times out - connection.socket.set_keepalive(true); - } catch (e) { - debug(e, 'Configuring Socket'); - } -} - - -/** - * Lan.ChannelService consists of two parts: - * - * The TCP Listener listens on a port and constructs a Channel object from the - * incoming Gio.TcpConnection. - * - * The UDP Listener listens on a port for incoming JSON identity packets which - * include the TCP port, while the IP address is taken from the UDP packet - * itself. We respond by opening a TCP connection to that address. - */ -export const ChannelService = GObject.registerClass({ - GTypeName: 'GSConnectLanChannelService', - Properties: { - 'certificate': GObject.ParamSpec.object( - 'certificate', - 'Certificate', - 'The TLS certificate', - GObject.ParamFlags.READWRITE, - Gio.TlsCertificate.$gtype - ), - 'port': GObject.ParamSpec.uint( - 'port', - 'Port', - 'The port used by the service', - GObject.ParamFlags.READWRITE, - 0, GLib.MAXUINT16, - PROTOCOL_PORT_DEFAULT - ), - }, -}, class LanChannelService extends Core.ChannelService { - - _init(params = {}) { - super._init(params); - - // Track hosts we identify to directly, allowing them to ignore the - // discoverable state of the service. - this._allowed = new Set(); - - // - this._tcp = null; - this._tcpPort = PROTOCOL_PORT_DEFAULT; - this._udp4 = null; - this._udp6 = null; - - // Monitor network status - this._networkMonitor = Gio.NetworkMonitor.get_default(); - this._networkAvailable = false; - this._networkChangedId = 0; - } - - get certificate() { - if (this._certificate === undefined) - this._certificate = null; - - return this._certificate; - } - - set certificate(certificate) { - if (this.certificate === certificate) - return; - - this._certificate = certificate; - this.notify('certificate'); - } - - get channels() { - if (this._channels === undefined) - this._channels = new Map(); - - return this._channels; - } - - get port() { - if (this._port === undefined) - this._port = PROTOCOL_PORT_DEFAULT; - - return this._port; - } - - set port(port) { - if (this.port === port) - return; - - this._port = port; - this.notify('port'); - } - - _onNetworkChanged(monitor, network_available) { - if (this._networkAvailable === network_available) - return; - - this._networkAvailable = network_available; - this.broadcast(); - } - - _initCertificate() { - if (GLib.find_program_in_path(Config.OPENSSL_PATH) === null) { - const error = new Error(); - error.name = _('OpenSSL not found'); - error.url = `${Config.PACKAGE_URL}/wiki/Error#openssl-not-found`; - throw error; - } - - const certPath = GLib.build_filenamev([ - Config.CONFIGDIR, - 'certificate.pem', - ]); - const keyPath = GLib.build_filenamev([ - Config.CONFIGDIR, - 'private.pem', - ]); - - // Ensure a certificate exists with our id as the common name - this._certificate = Gio.TlsCertificate.new_for_paths(certPath, keyPath, - this.id); - - // If the service ID doesn't match the common name, this is probably a - // certificate from an older version and we should amend ours to match - if (this.id !== this._certificate.common_name) - this._id = this._certificate.common_name; - } - - _initTcpListener() { - try { - this._tcp = new Gio.SocketService(); - - let tcpPort = this.port; - const tcpPortMax = tcpPort + - (PROTOCOL_PORT_MAX - PROTOCOL_PORT_MIN); - - while (tcpPort <= tcpPortMax) { - try { - this._tcp.add_inet_port(tcpPort, null); - break; - } catch (e) { - if (tcpPort < tcpPortMax) { - tcpPort++; - continue; - } - - throw e; - } - } - - this._tcpPort = tcpPort; - this._tcp.connect('incoming', this._onIncomingChannel.bind(this)); - } catch (e) { - this._tcp.stop(); - this._tcp.close(); - this._tcp = null; - - throw e; - } - } - - async _onIncomingChannel(listener, connection) { - try { - const host = connection.get_remote_address().address.to_string(); - - // Create a channel - const channel = new Channel({ - backend: this, - certificate: this.certificate, - host: host, - port: this.port, - }); - - // Accept the connection - await channel.accept(connection); - channel.identity.body.tcpHost = channel.host; - channel.identity.body.tcpPort = this._tcpPort; - channel.allowed = this._allowed.has(host); - - this.channel(channel); - } catch (e) { - debug(e); - } - } - - _initUdpListener() { - // Default broadcast address - this._udp_address = Gio.InetSocketAddress.new_from_string( - '255.255.255.255', this.port); - - try { - this._udp6 = Gio.Socket.new(Gio.SocketFamily.IPV6, - Gio.SocketType.DATAGRAM, Gio.SocketProtocol.UDP); - this._udp6.set_broadcast(true); - - // Bind the socket - const inetAddr = Gio.InetAddress.new_any(Gio.SocketFamily.IPV6); - const sockAddr = Gio.InetSocketAddress.new(inetAddr, this.port); - this._udp6.bind(sockAddr, true); - - // Input stream - this._udp6_stream = new Gio.DataInputStream({ - base_stream: new GioUnix.InputStream({ - fd: this._udp6.fd, - close_fd: false, - }), - }); - - // Watch socket for incoming packets - this._udp6_source = this._udp6.create_source(GLib.IOCondition.IN, null); - this._udp6_source.set_callback(this._onIncomingIdentity.bind(this, this._udp6)); - this._udp6_source.attach(null); - } catch (e) { - this._udp6 = null; - } - - // Our IPv6 socket also supports IPv4; we're all done - if (this._udp6 && this._udp6.speaks_ipv4()) { - this._udp4 = null; - return; - } - - try { - this._udp4 = Gio.Socket.new(Gio.SocketFamily.IPV4, - Gio.SocketType.DATAGRAM, Gio.SocketProtocol.UDP); - this._udp4.set_broadcast(true); - - // Bind the socket - const inetAddr = Gio.InetAddress.new_any(Gio.SocketFamily.IPV4); - const sockAddr = Gio.InetSocketAddress.new(inetAddr, this.port); - this._udp4.bind(sockAddr, true); - - // Input stream - this._udp4_stream = new Gio.DataInputStream({ - base_stream: new GioUnix.InputStream({ - fd: this._udp4.fd, - close_fd: false, - }), - }); - - // Watch input socket for incoming packets - this._udp4_source = this._udp4.create_source(GLib.IOCondition.IN, null); - this._udp4_source.set_callback(this._onIncomingIdentity.bind(this, this._udp4)); - this._udp4_source.attach(null); - } catch (e) { - this._udp4 = null; - - // We failed to get either an IPv4 or IPv6 socket to bind - if (this._udp6 === null) - throw e; - } - } - - _onIncomingIdentity(socket) { - let host; - - // Try to peek the remote address - try { - host = socket.receive_message([], Gio.SocketMsgFlags.PEEK, null)[1] - .address.to_string(); - } catch (e) { - logError(e); - } - - // Whether or not we peeked the address, we need to read the packet - try { - let data; - - if (socket === this._udp6) - data = this._udp6_stream.read_line_utf8(null)[0]; - else - data = this._udp4_stream.read_line_utf8(null)[0]; - - // Discard the packet if we failed to peek the address - if (host === undefined) - return GLib.SOURCE_CONTINUE; - - const packet = new Core.Packet(data); - packet.body.tcpHost = host; - this._onIdentity(packet); - } catch (e) { - logError(e); - } - - return GLib.SOURCE_CONTINUE; - } - - async _onIdentity(packet) { - try { - // Bail if the deviceId is missing - if (!packet.body.hasOwnProperty('deviceId')) - return; - - // Silently ignore our own broadcasts - if (packet.body.deviceId === this.identity.body.deviceId) - return; - - debug(packet); - - // Create a new channel - const channel = new Channel({ - backend: this, - certificate: this.certificate, - host: packet.body.tcpHost, - port: packet.body.tcpPort, - identity: packet, - }); - - // Check if channel is already open with this address - if (this.channels.has(channel.address)) - return; - - this._channels.set(channel.address, channel); - - // Open a TCP connection - const address = Gio.InetSocketAddress.new_from_string( - packet.body.tcpHost, packet.body.tcpPort); - - const client = new Gio.SocketClient({enable_proxy: false}); - const connection = await client.connect_async(address, - this.cancellable); - - // Connect the channel and attach it to the device on success - await channel.open(connection); - - this.channel(channel); - } catch (e) { - logError(e); - } - } - - /** - * Broadcast an identity packet - * - * If @address is not %null it may specify an IPv4 or IPv6 address to send - * the identity packet directly to, otherwise it will be broadcast to the - * default address, 255.255.255.255. - * - * @param {string} [address] - An optional target IPv4 or IPv6 address - */ - broadcast(address = null) { - try { - if (!this._networkAvailable) - return; - - // Try to parse strings as : - if (typeof address === 'string') { - const [host, portstr] = address.split(':'); - const port = parseInt(portstr) || this.port; - address = Gio.InetSocketAddress.new_from_string(host, port); - } - - // If we succeed, remember this host - if (address instanceof Gio.InetSocketAddress) { - this._allowed.add(address.address.to_string()); - - // Broadcast to the network if no address is specified - } else { - debug('Broadcasting to LAN'); - address = this._udp_address; - } - - // Broadcast on each open socket - if (this._udp6 !== null) - this._udp6.send_to(address, this.identity.serialize(), null); - - if (this._udp4 !== null) - this._udp4.send_to(address, this.identity.serialize(), null); - } catch (e) { - debug(e, address); - } - } - - buildIdentity() { - // Chain-up, then add the TCP port - super.buildIdentity(); - this.identity.body.tcpPort = this._tcpPort; - } - - start() { - if (this.active) - return; - - // Ensure a certificate exists - if (this.certificate === null) - this._initCertificate(); - - // Start TCP/UDP listeners - try { - if (this._tcp === null) - this._initTcpListener(); - - if (this._udp4 === null && this._udp6 === null) - this._initUdpListener(); - } catch (e) { - // Known case of another application using the protocol defined port - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.ADDRESS_IN_USE)) { - e.name = _('Port already in use'); - e.url = `${Config.PACKAGE_URL}/wiki/Error#port-already-in-use`; - } - - throw e; - } - - // Monitor network changes - if (this._networkChangedId === 0) { - this._networkAvailable = this._networkMonitor.network_available; - this._networkChangedId = this._networkMonitor.connect( - 'network-changed', this._onNetworkChanged.bind(this)); - } - - this._active = true; - this.notify('active'); - } - - stop() { - if (this._networkChangedId) { - this._networkMonitor.disconnect(this._networkChangedId); - this._networkChangedId = 0; - this._networkAvailable = false; - } - - if (this._tcp !== null) { - this._tcp.stop(); - this._tcp.close(); - this._tcp = null; - } - - if (this._udp6 !== null) { - this._udp6_source.destroy(); - this._udp6_stream.close(null); - this._udp6.close(); - this._udp6 = null; - } - - if (this._udp4 !== null) { - this._udp4_source.destroy(); - this._udp4_stream.close(null); - this._udp4.close(); - this._udp4 = null; - } - - for (const channel of this.channels.values()) - channel.close(); - - this._active = false; - this.notify('active'); - } - - destroy() { - try { - this.stop(); - } catch (e) { - debug(e); - } - } -}); - - -/** - * Lan Channel - * - * This class essentially just extends Core.Channel to set TCP socket options - * and negotiate TLS encrypted connections. - */ -export const Channel = GObject.registerClass({ - GTypeName: 'GSConnectLanChannel', -}, class LanChannel extends Core.Channel { - - _init(params) { - super._init(); - Object.assign(this, params); - } - - get address() { - return `lan://${this.host}:${this.port}`; - } - - get certificate() { - if (this._certificate === undefined) - this._certificate = null; - - return this._certificate; - } - - set certificate(certificate) { - this._certificate = certificate; - } - - get peer_certificate() { - if (this._connection instanceof Gio.TlsConnection) - return this._connection.get_peer_certificate(); - - return null; - } - - get host() { - if (this._host === undefined) - this._host = null; - - return this._host; - } - - set host(host) { - this._host = host; - } - - get port() { - if (this._port === undefined) { - if (this.identity && this.identity.body.tcpPort) - this._port = this.identity.body.tcpPort; - else - return PROTOCOL_PORT_DEFAULT; - } - - return this._port; - } - - set port(port) { - this._port = port; - } - - /** - * Authenticate a TLS connection. - * - * @param {Gio.TlsConnection} connection - A TLS connection - * @return {Promise} A promise for the operation - */ - async _authenticate(connection) { - // Standard TLS Handshake - connection.validation_flags = Gio.TlsCertificateFlags.EXPIRED; - connection.authentication_mode = Gio.TlsAuthenticationMode.REQUIRED; - - await connection.handshake_async(GLib.PRIORITY_DEFAULT, - this.cancellable); - - // Get a settings object for the device - let settings; - - if (this.device) { - settings = this.device.settings; - } else { - const id = this.identity.body.deviceId; - settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect.Device', - true - ), - path: `/org/gnome/shell/extensions/gsconnect/device/${id}/`, - }); - } - - // If we have a certificate for this deviceId, we can verify it - const cert_pem = settings.get_string('certificate-pem'); - - if (cert_pem !== '') { - let certificate = null; - let verified = false; - - try { - certificate = Gio.TlsCertificate.new_from_pem(cert_pem, -1); - verified = certificate.is_same(connection.peer_certificate); - } catch (e) { - logError(e); - } - - /* The certificate is incorrect for one of two reasons, but both - * result in us resetting the certificate and unpairing the device. - * - * If the certificate failed to load, it is probably corrupted or - * otherwise invalid. In this case, if we try to continue we will - * certainly crash the Android app. - * - * If the certificate did not match what we expected the obvious - * thing to do is to notify the user, however experience tells us - * this is a result of the user doing something masochistic like - * nuking the Android app data or copying settings between machines. - */ - if (verified === false) { - if (this.device) { - this.device.unpair(); - } else { - settings.reset('paired'); - settings.reset('certificate-pem'); - } - - const name = this.identity.body.deviceName; - throw new Error(`${name}: Authentication Failure`); - } - } - - return connection; - } - - /** - * Wrap the connection in Gio.TlsClientConnection and initiate handshake - * - * @param {Gio.TcpConnection} connection - The unauthenticated connection - * @return {Gio.TlsClientConnection} The authenticated connection - */ - _encryptClient(connection) { - _configureSocket(connection); - - connection = Gio.TlsClientConnection.new(connection, - connection.socket.remote_address); - connection.set_certificate(this.certificate); - - return this._authenticate(connection); - } - - /** - * Wrap the connection in Gio.TlsServerConnection and initiate handshake - * - * @param {Gio.TcpConnection} connection - The unauthenticated connection - * @return {Gio.TlsServerConnection} The authenticated connection - */ - _encryptServer(connection) { - _configureSocket(connection); - - connection = Gio.TlsServerConnection.new(connection, this.certificate); - - // We're the server so we trust-on-first-use and verify after - const _id = connection.connect('accept-certificate', (connection) => { - connection.disconnect(_id); - return true; - }); - - return this._authenticate(connection); - } - - /** - * Negotiate an incoming connection - * - * @param {Gio.TcpConnection} connection - The incoming connection - */ - async accept(connection) { - debug(`${this.address} (${this.uuid})`); - - try { - this._connection = connection; - this.backend.channels.set(this.address, this); - - // In principle this disposable wrapper could buffer more than the - // identity packet, but in practice the remote device shouldn't send - // any more data until the TLS connection is negotiated. - const stream = new Gio.DataInputStream({ - base_stream: connection.input_stream, - close_base_stream: false, - }); - - const data = await stream.read_line_async(GLib.PRIORITY_DEFAULT, - this.cancellable); - stream.close_async(GLib.PRIORITY_DEFAULT, null, null); - - this.identity = new Core.Packet(data[0]); - - if (!this.identity.body.deviceId) - throw new Error('missing deviceId'); - - this._connection = await this._encryptClient(connection); - } catch (e) { - this.close(); - throw e; - } - } - - /** - * Negotiate an outgoing connection - * - * @param {Gio.SocketConnection} connection - The remote connection - */ - async open(connection) { - debug(`${this.address} (${this.uuid})`); - - try { - this._connection = connection; - this.backend.channels.set(this.address, this); - - await connection.get_output_stream().write_all_async( - this.backend.identity.serialize(), - GLib.PRIORITY_DEFAULT, - this.cancellable); - - this._connection = await this._encryptServer(connection); - } catch (e) { - this.close(); - throw e; - } - } - - /** - * Close all streams associated with this channel, silencing any errors - */ - close() { - if (this.closed) - return; - - debug(`${this.address} (${this.uuid})`); - this._closed = true; - this.notify('closed'); - - this.backend.channels.delete(this.address); - this.cancellable.cancel(); - - if (this._connection) - this._connection.close_async(GLib.PRIORITY_DEFAULT, null, null); - - if (this.input_stream) - this.input_stream.close_async(GLib.PRIORITY_DEFAULT, null, null); - - if (this.output_stream) - this.output_stream.close_async(GLib.PRIORITY_DEFAULT, null, null); - } - - async download(packet, target, cancellable = null) { - const address = Gio.InetSocketAddress.new_from_string(this.host, - packet.payloadTransferInfo.port); - - const client = new Gio.SocketClient({enable_proxy: false}); - const connection = await client.connect_async(address, cancellable) - .then(this._encryptClient.bind(this)); - - // Start the transfer - const transferredSize = await target.splice_async( - connection.input_stream, - (Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | - Gio.OutputStreamSpliceFlags.CLOSE_TARGET), - GLib.PRIORITY_DEFAULT, cancellable); - - // If we get less than expected, we've certainly got corruption - if (transferredSize < packet.payloadSize) { - throw new Gio.IOErrorEnum({ - code: Gio.IOErrorEnum.FAILED, - message: `Incomplete: ${transferredSize}/${packet.payloadSize}`, - }); - - // TODO: sometimes kdeconnect-android under-reports a file's size - // https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/1157 - } else if (transferredSize > packet.payloadSize) { - logError(new Gio.IOErrorEnum({ - code: Gio.IOErrorEnum.FAILED, - message: `Extra Data: ${transferredSize - packet.payloadSize}`, - })); - } - } - - async upload(packet, source, size, cancellable = null) { - // Start listening on the first available port between 1739-1764 - const listener = new Gio.SocketListener(); - let port = TRANSFER_MIN; - - while (port <= TRANSFER_MAX) { - try { - listener.add_inet_port(port, null); - break; - } catch (e) { - if (port < TRANSFER_MAX) { - port++; - continue; - } else { - throw e; - } - } - } - - // Listen for the incoming connection - const acceptConnection = listener.accept_async(cancellable) - .then(result => this._encryptServer(result[0])); - - // Create an upload request - packet.body.payloadHash = this.checksum; - packet.payloadSize = size; - packet.payloadTransferInfo = {port: port}; - const requestUpload = this.sendPacket(new Core.Packet(packet), - cancellable); - - // Request an upload stream, accept the connection and get the output - const [, connection] = await Promise.all([requestUpload, - acceptConnection]); - - // Start the transfer - const transferredSize = await connection.output_stream.splice_async( - source, - (Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | - Gio.OutputStreamSpliceFlags.CLOSE_TARGET), - GLib.PRIORITY_DEFAULT, cancellable); - - if (transferredSize !== size) { - throw new Gio.IOErrorEnum({ - code: Gio.IOErrorEnum.PARTIAL_INPUT, - message: 'Transfer incomplete', - }); - } - } - - async rejectTransfer(packet) { - try { - if (!packet || !packet.hasPayload()) - return; - - if (packet.payloadTransferInfo.port === undefined) - return; - - const address = Gio.InetSocketAddress.new_from_string(this.host, - packet.payloadTransferInfo.port); - - const client = new Gio.SocketClient({enable_proxy: false}); - const connection = await client.connect_async(address, null) - .then(this._encryptClient.bind(this)); - - connection.close_async(GLib.PRIORITY_DEFAULT, null, null); - } catch (e) { - debug(e, this.device.name); - } - } -}); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/atspi.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/atspi.js deleted file mode 100755 index 97581d7a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/atspi.js +++ /dev/null @@ -1,312 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Atspi from 'gi://Atspi?version=2.0'; -import Gdk from 'gi://Gdk'; - - -/** - * Printable ASCII range - */ -const _ASCII = /[\x20-\x7E]/; - - -/** - * Modifier Keycode Defaults - */ -const XKeycode = { - Alt_L: 0x40, - Control_L: 0x25, - Shift_L: 0x32, - Super_L: 0x85, -}; - - -/** - * A thin wrapper around Atspi for X11 sessions without Pipewire support. - */ -export default class Controller { - constructor() { - // Atspi.init() return 2 on fail, but still marks itself as inited. We - // uninit before throwing an error otherwise any future call to init() - // will appear successful and other calls will cause GSConnect to exit. - // See: https://gitlab.gnome.org/GNOME/at-spi2-core/blob/master/atspi/atspi-misc.c - if (Atspi.init() === 2) { - this.destroy(); - throw new Error('Failed to start AT-SPI'); - } - - try { - this._display = Gdk.Display.get_default(); - this._seat = this._display.get_default_seat(); - this._pointer = this._seat.get_pointer(); - } catch (e) { - this.destroy(); - throw e; - } - - // Try to read modifier keycodes from Gdk - try { - const keymap = Gdk.Keymap.get_for_display(this._display); - let modifier; - - modifier = keymap.get_entries_for_keyval(Gdk.KEY_Alt_L)[1][0]; - XKeycode.Alt_L = modifier.keycode; - - modifier = keymap.get_entries_for_keyval(Gdk.KEY_Control_L)[1][0]; - XKeycode.Control_L = modifier.keycode; - - modifier = keymap.get_entries_for_keyval(Gdk.KEY_Shift_L)[1][0]; - XKeycode.Shift_L = modifier.keycode; - - modifier = keymap.get_entries_for_keyval(Gdk.KEY_Super_L)[1][0]; - XKeycode.Super_L = modifier.keycode; - } catch (e) { - debug('using default modifier keycodes'); - } - } - - /* - * Pointer events - */ - clickPointer(button) { - try { - const [, x, y] = this._pointer.get_position(); - const monitor = this._display.get_monitor_at_point(x, y); - const scale = monitor.get_scale_factor(); - Atspi.generate_mouse_event(scale * x, scale * y, `b${button}c`); - } catch (e) { - logError(e); - } - } - - doubleclickPointer(button) { - try { - const [, x, y] = this._pointer.get_position(); - const monitor = this._display.get_monitor_at_point(x, y); - const scale = monitor.get_scale_factor(); - Atspi.generate_mouse_event(scale * x, scale * y, `b${button}d`); - } catch (e) { - logError(e); - } - } - - movePointer(dx, dy) { - try { - const [, x, y] = this._pointer.get_position(); - const monitor = this._display.get_monitor_at_point(x, y); - const scale = monitor.get_scale_factor(); - Atspi.generate_mouse_event(scale * dx, scale * dy, 'rel'); - } catch (e) { - logError(e); - } - } - - pressPointer(button) { - try { - const [, x, y] = this._pointer.get_position(); - const monitor = this._display.get_monitor_at_point(x, y); - const scale = monitor.get_scale_factor(); - Atspi.generate_mouse_event(scale * x, scale * y, `b${button}p`); - } catch (e) { - logError(e); - } - } - - releasePointer(button) { - try { - const [, x, y] = this._pointer.get_position(); - const monitor = this._display.get_monitor_at_point(x, y); - const scale = monitor.get_scale_factor(); - Atspi.generate_mouse_event(scale * x, scale * y, `b${button}r`); - } catch (e) { - logError(e); - } - } - - scrollPointer(dx, dy) { - if (dy > 0) - this.clickPointer(4); - else if (dy < 0) - this.clickPointer(5); - } - - /* - * Phony virtual keyboard helpers - */ - _modeLock(keycode) { - Atspi.generate_keyboard_event( - keycode, - null, - Atspi.KeySynthType.PRESS - ); - } - - _modeUnlock(keycode) { - Atspi.generate_keyboard_event( - keycode, - null, - Atspi.KeySynthType.RELEASE - ); - } - - /* - * Simulate a printable-ASCII character. - * - */ - _pressASCII(key, modifiers) { - try { - // Press Modifiers - if (modifiers & Gdk.ModifierType.MOD1_MASK) - this._modeLock(XKeycode.Alt_L); - if (modifiers & Gdk.ModifierType.CONTROL_MASK) - this._modeLock(XKeycode.Control_L); - if (modifiers & Gdk.ModifierType.SHIFT_MASK) - this._modeLock(XKeycode.Shift_L); - if (modifiers & Gdk.ModifierType.SUPER_MASK) - this._modeLock(XKeycode.Super_L); - - Atspi.generate_keyboard_event( - 0, - key, - Atspi.KeySynthType.STRING - ); - - // Release Modifiers - if (modifiers & Gdk.ModifierType.MOD1_MASK) - this._modeUnlock(XKeycode.Alt_L); - if (modifiers & Gdk.ModifierType.CONTROL_MASK) - this._modeUnlock(XKeycode.Control_L); - if (modifiers & Gdk.ModifierType.SHIFT_MASK) - this._modeUnlock(XKeycode.Shift_L); - if (modifiers & Gdk.ModifierType.SUPER_MASK) - this._modeUnlock(XKeycode.Super_L); - } catch (e) { - logError(e); - } - } - - _pressKeysym(keysym, modifiers) { - try { - // Press Modifiers - if (modifiers & Gdk.ModifierType.MOD1_MASK) - this._modeLock(XKeycode.Alt_L); - if (modifiers & Gdk.ModifierType.CONTROL_MASK) - this._modeLock(XKeycode.Control_L); - if (modifiers & Gdk.ModifierType.SHIFT_MASK) - this._modeLock(XKeycode.Shift_L); - if (modifiers & Gdk.ModifierType.SUPER_MASK) - this._modeLock(XKeycode.Super_L); - - Atspi.generate_keyboard_event( - keysym, - null, - Atspi.KeySynthType.PRESSRELEASE | Atspi.KeySynthType.SYM - ); - - // Release Modifiers - if (modifiers & Gdk.ModifierType.MOD1_MASK) - this._modeUnlock(XKeycode.Alt_L); - if (modifiers & Gdk.ModifierType.CONTROL_MASK) - this._modeUnlock(XKeycode.Control_L); - if (modifiers & Gdk.ModifierType.SHIFT_MASK) - this._modeUnlock(XKeycode.Shift_L); - if (modifiers & Gdk.ModifierType.SUPER_MASK) - this._modeUnlock(XKeycode.Super_L); - } catch (e) { - logError(e); - } - } - - /** - * Simulate the composition of a unicode character with: - * Control+Shift+u, [hex], Return - * - * @param {number} key - An XKeycode - * @param {number} modifiers - A modifier mask - */ - _pressUnicode(key, modifiers) { - try { - if (modifiers > 0) - log('GSConnect: ignoring modifiers for unicode keyboard event'); - - // TODO: Using Control and Shift keysym is not working (it triggers - // key release). Probably using LOCKMODIFIERS will not work either - // as unlocking the modifier will not trigger a release - - // Activate compose sequence - this._modeLock(XKeycode.Control_L); - this._modeLock(XKeycode.Shift_L); - - this.pressreleaseKeysym(Gdk.KEY_U); - - this._modeUnlock(XKeycode.Control_L); - this._modeUnlock(XKeycode.Shift_L); - - // Enter the unicode sequence - const ucode = key.charCodeAt(0).toString(16); - let keysym; - - for (let h = 0, len = ucode.length; h < len; h++) { - keysym = Gdk.unicode_to_keyval(ucode.charAt(h).codePointAt(0)); - this.pressreleaseKeysym(keysym); - } - - // Finish the compose sequence - this.pressreleaseKeysym(Gdk.KEY_Return); - } catch (e) { - logError(e); - } - } - - /* - * Keyboard Events - */ - pressKeysym(keysym) { - Atspi.generate_keyboard_event( - keysym, - null, - Atspi.KeySynthType.PRESS | Atspi.KeySynthType.SYM - ); - } - - releaseKeysym(keysym) { - Atspi.generate_keyboard_event( - keysym, - null, - Atspi.KeySynthType.RELEASE | Atspi.KeySynthType.SYM - ); - } - - pressreleaseKeysym(keysym) { - Atspi.generate_keyboard_event( - keysym, - null, - Atspi.KeySynthType.PRESSRELEASE | Atspi.KeySynthType.SYM - ); - } - - pressKey(input, modifiers) { - // We were passed a keysym - if (typeof input === 'number') - this._pressKeysym(input, modifiers); - - // Regular ASCII - else if (_ASCII.test(input)) - this._pressASCII(input, modifiers); - - // Unicode - else - this._pressUnicode(input, modifiers); - } - - destroy() { - try { - Atspi.exit(); - } catch (e) { - // Silence errors - } - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/clipboard.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/clipboard.js deleted file mode 100755 index 2d6170c4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/clipboard.js +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import GLib from 'gi://GLib'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; - - -const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard'; -const DBUS_PATH = '/org/gnome/Shell/Extensions/GSConnect/Clipboard'; - - -/** - * The service class for this component - */ -const Clipboard = GObject.registerClass({ - GTypeName: 'GSConnectClipboard', - Properties: { - 'text': GObject.ParamSpec.string( - 'text', - 'Text Content', - 'The current text content of the clipboard', - GObject.ParamFlags.READWRITE, - '' - ), - }, -}, class Clipboard extends GObject.Object { - - _init() { - super._init(); - - this._cancellable = new Gio.Cancellable(); - this._clipboard = null; - - this._ownerChangeId = 0; - this._nameWatcherId = Gio.bus_watch_name( - Gio.BusType.SESSION, - DBUS_NAME, - Gio.BusNameWatcherFlags.NONE, - this._onNameAppeared.bind(this), - this._onNameVanished.bind(this) - ); - } - - get text() { - if (this._text === undefined) - this._text = ''; - - return this._text; - } - - set text(content) { - if (this.text === content) - return; - - this._text = content; - this.notify('text'); - - if (typeof content !== 'string') - return; - - if (this._clipboard instanceof Gtk.Clipboard) - this._clipboard.set_text(content, -1); - - if (this._clipboard instanceof Gio.DBusProxy) { - this._clipboard.call('SetText', new GLib.Variant('(s)', [content]), - Gio.DBusCallFlags.NO_AUTO_START, -1, this._cancellable) - .catch(debug); - } - } - - async _onNameAppeared(connection, name, name_owner) { - try { - // Cleanup the GtkClipboard - if (this._clipboard && this._ownerChangeId > 0) { - this._clipboard.disconnect(this._ownerChangeId); - this._ownerChangeId = 0; - } - - // Create a proxy for the remote clipboard - this._clipboard = new Gio.DBusProxy({ - g_bus_type: Gio.BusType.SESSION, - g_name: DBUS_NAME, - g_object_path: DBUS_PATH, - g_interface_name: DBUS_NAME, - g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES, - }); - - await this._clipboard.init_async(GLib.PRIORITY_DEFAULT, - this._cancellable); - - this._ownerChangeId = this._clipboard.connect('g-signal', - this._onOwnerChange.bind(this)); - - this._onOwnerChange(); - if (!globalThis.HAVE_GNOME) { - // Directly subscrible signal - this.signalHandler = Gio.DBus.session.signal_subscribe( - DBUS_NAME, - DBUS_NAME, - 'OwnerChange', - DBUS_PATH, - null, - Gio.DBusSignalFlags.NONE, - this._onOwnerChange.bind(this) - ); - } - - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - debug(e); - this._onNameVanished(null, null); - } - } - } - - _onNameVanished(connection, name) { - if (this._clipboard && this._ownerChangeId > 0) { - this._clipboard.disconnect(this._ownerChangeId); - this._clipboardChangedId = 0; - } - - const display = Gdk.Display.get_default(); - this._clipboard = Gtk.Clipboard.get_default(display); - - this._ownerChangeId = this._clipboard.connect('owner-change', - this._onOwnerChange.bind(this)); - - this._onOwnerChange(); - } - - async _onOwnerChange() { - try { - if (this._clipboard instanceof Gtk.Clipboard) - await this._gtkUpdateText(); - - else if (this._clipboard instanceof Gio.DBusProxy) - await this._proxyUpdateText(); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - debug(e); - } - } - - _applyUpdate(text) { - if (typeof text !== 'string' || this.text === text) - return; - - this._text = text; - this.notify('text'); - } - - /* - * Proxy Clipboard - */ - async _proxyUpdateText() { - let reply = await this._clipboard.call('GetMimetypes', null, - Gio.DBusCallFlags.NO_AUTO_START, -1, this._cancellable); - const mimetypes = reply.deepUnpack()[0]; - - // Special case for a cleared clipboard - if (mimetypes.length === 0) - return this._applyUpdate(''); - - // Special case to ignore copied files - if (mimetypes.includes('text/uri-list')) - return; - - reply = await this._clipboard.call('GetText', null, - Gio.DBusCallFlags.NO_AUTO_START, -1, this._cancellable); - const text = reply.deepUnpack()[0]; - - this._applyUpdate(text); - } - - /* - * GtkClipboard - */ - async _gtkUpdateText() { - const mimetypes = await new Promise((resolve, reject) => { - this._clipboard.request_targets((clipboard, atoms) => resolve(atoms)); - }); - - // Special case for a cleared clipboard - if (mimetypes.length === 0) - return this._applyUpdate(''); - - // Special case to ignore copied files - if (mimetypes.includes('text/uri-list')) - return; - - const text = await new Promise((resolve, reject) => { - this._clipboard.request_text((clipboard, text) => resolve(text)); - }); - - this._applyUpdate(text); - } - - destroy() { - if (this._cancellable.is_cancelled()) - return; - - this._cancellable.cancel(); - - if (this._clipboard && this._ownerChangeId > 0) { - this._clipboard.disconnect(this._ownerChangeId); - this._ownerChangedId = 0; - } - - if (this._nameWatcherId > 0) { - Gio.bus_unwatch_name(this._nameWatcherId); - this._nameWatcherId = 0; - } - - if (!globalThis.HAVE_GNOME && this.signalHandler) - Gio.DBus.session.signal_unsubscribe(this.signalHandler); - } -}); - -export default Clipboard; - -// vim:tabstop=2:shiftwidth=2:expandtab diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/contacts.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/contacts.js deleted file mode 100755 index 3070f408..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/contacts.js +++ /dev/null @@ -1,613 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../../config.js'; - -let HAVE_EDS = true; -let EBook = null; -let EBookContacts = null; -let EDataServer = null; - -try { - EBook = (await import('gi://EBook')).default; - EBookContacts = (await import('gi://EBookContacts')).default; - EDataServer = (await import('gi://EDataServer')).default; -} catch (e) { - HAVE_EDS = false; -} - - -/** - * A store for contacts - */ -const Store = GObject.registerClass({ - GTypeName: 'GSConnectContactsStore', - Properties: { - 'context': GObject.ParamSpec.string( - 'context', - 'Context', - 'Used as the cache directory, relative to Config.CACHEDIR', - GObject.ParamFlags.CONSTRUCT_ONLY | GObject.ParamFlags.READWRITE, - null - ), - }, - Signals: { - 'contact-added': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [GObject.TYPE_STRING], - }, - 'contact-removed': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [GObject.TYPE_STRING], - }, - 'contact-changed': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [GObject.TYPE_STRING], - }, - }, -}, class Store extends GObject.Object { - - _init(context = null) { - super._init({ - context: context, - }); - - this._cacheData = {}; - this._edsPrepared = false; - } - - /** - * Parse an EContact and add it to the store. - * - * @param {EBookContacts.Contact} econtact - an EContact to parse - * @param {string} [origin] - an optional origin string - */ - async _parseEContact(econtact, origin = 'desktop') { - try { - const contact = { - id: econtact.id, - name: _('Unknown Contact'), - numbers: [], - origin: origin, - timestamp: 0, - }; - - // Try to get a contact name - if (econtact.full_name) - contact.name = econtact.full_name; - - // Parse phone numbers - const nums = econtact.get_attributes(EBookContacts.ContactField.TEL); - - for (const attr of nums) { - const number = { - value: attr.get_value(), - type: 'unknown', - }; - - if (attr.has_type('CELL')) - number.type = 'cell'; - else if (attr.has_type('HOME')) - number.type = 'home'; - else if (attr.has_type('WORK')) - number.type = 'work'; - - contact.numbers.push(number); - } - - // Try and get a contact photo - const photo = econtact.photo; - - if (photo) { - if (photo.type === EBookContacts.ContactPhotoType.INLINED) { - const data = photo.get_inlined()[0]; - contact.avatar = await this.storeAvatar(data); - - } else if (photo.type === EBookContacts.ContactPhotoType.URI) { - const uri = econtact.photo.get_uri(); - contact.avatar = uri.replace('file://', ''); - } - } - - this.add(contact, false); - } catch (e) { - logError(e, `Failed to parse VCard contact ${econtact.id}`); - } - } - - /* - * AddressBook DBus callbacks - */ - _onObjectsAdded(connection, sender, path, iface, signal, params) { - try { - const adds = params.get_child_value(0).get_strv(); - - // NOTE: sequential pairs of vcard, id - for (let i = 0, len = adds.length; i < len; i += 2) { - try { - const vcard = adds[i]; - const econtact = EBookContacts.Contact.new_from_vcard(vcard); - this._parseEContact(econtact); - } catch (e) { - debug(e); - } - } - } catch (e) { - debug(e); - } - } - - _onObjectsRemoved(connection, sender, path, iface, signal, params) { - try { - const changes = params.get_child_value(0).get_strv(); - - for (const id of changes) { - try { - this.remove(id, false); - } catch (e) { - debug(e); - } - } - } catch (e) { - debug(e); - } - } - - _onObjectsModified(connection, sender, path, iface, signal, params) { - try { - const changes = params.get_child_value(0).get_strv(); - - // NOTE: sequential pairs of vcard, id - for (let i = 0, len = changes.length; i < len; i += 2) { - try { - const vcard = changes[i]; - const econtact = EBookContacts.Contact.new_from_vcard(vcard); - this._parseEContact(econtact); - } catch (e) { - debug(e); - } - } - } catch (e) { - debug(e); - } - } - - /* - * SourceRegistryWatcher callbacks - */ - async _onAppeared(watcher, source) { - try { - // Get an EBookClient and EBookView - const uid = source.get_uid(); - const client = await EBook.BookClient.connect(source, null); - const [view] = await client.get_view('exists "tel"', null); - - // Watch the view for changes to the address book - const connection = view.get_connection(); - const objectPath = view.get_object_path(); - - view._objectsAddedId = connection.signal_subscribe( - null, - 'org.gnome.evolution.dataserver.AddressBookView', - 'ObjectsAdded', - objectPath, - null, - Gio.DBusSignalFlags.NONE, - this._onObjectsAdded.bind(this) - ); - - view._objectsRemovedId = connection.signal_subscribe( - null, - 'org.gnome.evolution.dataserver.AddressBookView', - 'ObjectsRemoved', - objectPath, - null, - Gio.DBusSignalFlags.NONE, - this._onObjectsRemoved.bind(this) - ); - - view._objectsModifiedId = connection.signal_subscribe( - null, - 'org.gnome.evolution.dataserver.AddressBookView', - 'ObjectsModified', - objectPath, - null, - Gio.DBusSignalFlags.NONE, - this._onObjectsModified.bind(this) - ); - - view.start(); - - // Store the EBook in a map - this._ebooks.set(uid, { - source: source, - client: client, - view: view, - }); - } catch (e) { - debug(e); - } - } - - _onDisappeared(watcher, source) { - try { - const uid = source.get_uid(); - const ebook = this._ebooks.get(uid); - - if (ebook === undefined) - return; - - // Disconnect the EBookView - if (ebook.view) { - const connection = ebook.view.get_connection(); - connection.signal_unsubscribe(ebook.view._objectsAddedId); - connection.signal_unsubscribe(ebook.view._objectsRemovedId); - connection.signal_unsubscribe(ebook.view._objectsModifiedId); - - ebook.view.stop(); - } - - this._ebooks.delete(uid); - } catch (e) { - debug(e); - } - } - - async _initEvolutionDataServer() { - try { - if (this._edsPrepared) - return; - - this._edsPrepared = true; - this._ebooks = new Map(); - - // Get the current EBooks - const registry = await this._getESourceRegistry(); - - for (const source of registry.list_sources('Address Book')) - await this._onAppeared(null, source); - - // Watch for new and removed sources - this._watcher = new EDataServer.SourceRegistryWatcher({ - registry: registry, - extension_name: 'Address Book', - }); - - this._appearedId = this._watcher.connect( - 'appeared', - this._onAppeared.bind(this) - ); - this._disappearedId = this._watcher.connect( - 'disappeared', - this._onDisappeared.bind(this) - ); - } catch (e) { - const service = Gio.Application.get_default(); - - if (service !== null) - service.notify_error(e); - else - logError(e); - } - } - - *[Symbol.iterator]() { - const contacts = Object.values(this._cacheData); - - for (let i = 0, len = contacts.length; i < len; i++) - yield contacts[i]; - } - - get contacts() { - return Object.values(this._cacheData); - } - - get context() { - if (this._context === undefined) - this._context = null; - - return this._context; - } - - set context(context) { - this._context = context; - this._cacheDir = Gio.File.new_for_path(Config.CACHEDIR); - - if (context !== null) - this._cacheDir = this._cacheDir.get_child(context); - - GLib.mkdir_with_parents(this._cacheDir.get_path(), 448); - this._cacheFile = this._cacheDir.get_child('contacts.json'); - } - - /** - * Save a Uint8Array to file and return the path - * - * @param {Uint8Array} contents - An image byte array - * @return {string|undefined} File path or %undefined on failure - */ - async storeAvatar(contents) { - const md5 = GLib.compute_checksum_for_data(GLib.ChecksumType.MD5, - contents); - const file = this._cacheDir.get_child(`${md5}`); - - if (!file.query_exists(null)) { - try { - await file.replace_contents_bytes_async( - new GLib.Bytes(contents), - null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null); - } catch (e) { - debug(e, 'Storing avatar'); - return undefined; - } - } - - return file.get_path(); - } - - /** - * Query the Store for a contact by name and/or number. - * - * @param {Object} query - A query object - * @param {string} [query.name] - The contact's name - * @param {string} query.number - The contact's number - * @return {Object} A contact object - */ - query(query) { - // First look for an existing contact by number - const contacts = this.contacts; - const matches = []; - const qnumber = query.number.toPhoneNumber(); - - for (let i = 0, len = contacts.length; i < len; i++) { - const contact = contacts[i]; - - for (const num of contact.numbers) { - const cnumber = num.value.toPhoneNumber(); - - if (qnumber.endsWith(cnumber) || cnumber.endsWith(qnumber)) { - // If no query name or exact match, return immediately - if (!query.name || query.name === contact.name) - return contact; - - // Otherwise we might find an exact name match that shares - // the number with another contact - matches.push(contact); - } - } - } - - // Return the first match (pretty much what Android does) - if (matches.length > 0) - return matches[0]; - - // No match; return a mock contact with a unique ID - let id = GLib.uuid_string_random(); - - while (this._cacheData.hasOwnProperty(id)) - id = GLib.uuid_string_random(); - - return { - id: id, - name: query.name || query.number, - numbers: [{value: query.number, type: 'unknown'}], - origin: 'gsconnect', - }; - } - - get_contact(position) { - if (this._cacheData[position] !== undefined) - return this._cacheData[position]; - - return null; - } - - /** - * Add a contact, checking for validity - * - * @param {Object} contact - A contact object - * @param {boolean} write - Write to disk - */ - add(contact, write = true) { - // Ensure the contact has a unique id - if (!contact.id) { - let id = GLib.uuid_string_random(); - - while (this._cacheData[id]) - id = GLib.uuid_string_random(); - - contact.id = id; - } - - // Ensure the contact has an origin - if (!contact.origin) - contact.origin = 'gsconnect'; - - // This is an updated contact - if (this._cacheData[contact.id]) { - this._cacheData[contact.id] = contact; - this.emit('contact-changed', contact.id); - - // This is a new contact - } else { - this._cacheData[contact.id] = contact; - this.emit('contact-added', contact.id); - } - - // Write if requested - if (write) - this.save(); - } - - /** - * Remove a contact by id - * - * @param {string} id - The id of the contact to delete - * @param {boolean} write - Write to disk - */ - remove(id, write = true) { - // Only remove if the contact actually exists - if (this._cacheData[id]) { - delete this._cacheData[id]; - this.emit('contact-removed', id); - - // Write if requested - if (write) - this.save(); - } - } - - /** - * Lookup a contact for each address object in @addresses and return a - * dictionary of address (eg. phone number) to contact object. - * - * { "555-5555": { "name": "...", "numbers": [], ... } } - * - * @param {Object[]} addresses - A list of address objects - * @return {Object} A dictionary of phone numbers and contacts - */ - lookupAddresses(addresses) { - const contacts = {}; - - // Lookup contacts for each address - for (let i = 0, len = addresses.length; i < len; i++) { - const address = addresses[i].address; - - contacts[address] = this.query({ - number: address, - }); - } - - return contacts; - } - - async clear() { - try { - const contacts = this.contacts; - - for (let i = 0, len = contacts.length; i < len; i++) - await this.remove(contacts[i].id, false); - - await this.save(); - } catch (e) { - debug(e); - } - } - - /** - * Update the contact store from a dictionary of our custom contact objects. - * - * @param {Object} json - an Object of contact Objects - */ - async update(json = {}) { - try { - let contacts = Object.values(json); - - for (let i = 0, len = contacts.length; i < len; i++) { - const new_contact = contacts[i]; - const contact = this._cacheData[new_contact.id]; - - if (!contact || new_contact.timestamp !== contact.timestamp) - await this.add(new_contact, false); - } - - // Prune contacts - contacts = this.contacts; - - for (let i = 0, len = contacts.length; i < len; i++) { - const contact = contacts[i]; - - if (!json[contact.id]) - await this.remove(contact.id, false); - } - - await this.save(); - } catch (e) { - debug(e, 'Updating contacts'); - } - } - - /** - * Fetch and update the contact store from its source. - * - * The default function initializes the EDS server, or logs a debug message - * if EDS is unavailable. Derived classes should request an update from the - * remote source. - */ - async fetch() { - try { - if (this.context === null && HAVE_EDS) - await this._initEvolutionDataServer(); - else - throw new Error('Evolution Data Server not available'); - } catch (e) { - debug(e); - } - } - - /** - * Load the contacts from disk. - */ - async load() { - try { - const [contents] = await this._cacheFile.load_contents_async(null); - this._cacheData = JSON.parse(new TextDecoder().decode(contents)); - } catch (e) { - debug(e); - } finally { - this.notify('context'); - } - } - - /** - * Save the contacts to disk. - */ - async save() { - // EDS is handling storage - if (this.context === null && HAVE_EDS) - return; - - if (this.__cache_lock) { - this.__cache_queue = true; - return; - } - - try { - this.__cache_lock = true; - - const contents = new GLib.Bytes(JSON.stringify(this._cacheData, null, 2)); - await this._cacheFile.replace_contents_bytes_async(contents, null, - false, Gio.FileCreateFlags.REPLACE_DESTINATION, null); - } catch (e) { - debug(e); - } finally { - this.__cache_lock = false; - - if (this.__cache_queue) { - this.__cache_queue = false; - this.save(); - } - } - } - - destroy() { - if (this._watcher !== undefined) { - this._watcher.disconnect(this._appearedId); - this._watcher.disconnect(this._disappearedId); - this._watcher = undefined; - - for (const ebook of this._ebooks.values()) - this._onDisappeared(null, ebook.source); - - this._edsPrepared = false; - } - } -}); - -export default Store; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/index.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/index.js deleted file mode 100755 index 249c7ee8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/index.js +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import * as atspi from './atspi.js'; -import * as clipboard from './clipboard.js'; -import * as contacts from './contacts.js'; -import * as input from './input.js'; -import * as mpris from './mpris.js'; -import * as notification from './notification.js'; -import * as pulseaudio from './pulseaudio.js'; -import * as session from './session.js'; -import * as sound from './sound.js'; -import * as upower from './upower.js'; -import * as ydotool from './ydotool.js'; - -export const functionOverrides = {}; - -const components = { - atspi, - clipboard, - contacts, - input, - mpris, - notification, - pulseaudio, - session, - sound, - upower, - ydotool, -}; - -/* - * Singleton Tracker - */ -const Default = new Map(); - - -/** - * Acquire a reference to a component. Calls to this function should always be - * followed by a call to `release()`. - * - * @param {string} name - The module name - * @return {*} The default instance of a component - */ -export function acquire(name) { - if (functionOverrides.acquire) - return functionOverrides.acquire(name); - - let component; - - try { - let info = Default.get(name); - - if (info === undefined) { - const module = components[name]; - - info = { - instance: new module.default(), - refcount: 0, - }; - - Default.set(name, info); - } - - info.refcount++; - component = info.instance; - } catch (e) { - debug(e, name); - } - - return component; -} - - -/** - * Release a reference on a component. If the caller was the last reference - * holder, the component will be freed. - * - * @param {string} name - The module name - * @return {null} A %null value, useful for overriding a traced variable - */ -export function release(name) { - if (functionOverrides.release) - return functionOverrides.release(name); - - try { - const info = Default.get(name); - - if (info.refcount === 1) { - info.instance.destroy(); - Default.delete(name); - } - - info.refcount--; - } catch (e) { - debug(e, name); - } - - return null; -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/input.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/input.js deleted file mode 100755 index 49fd65f9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/input.js +++ /dev/null @@ -1,514 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import AtspiController from './atspi.js'; - - -const SESSION_TIMEOUT = 15; - - -const RemoteSession = GObject.registerClass({ - GTypeName: 'GSConnectRemoteSession', - Implements: [Gio.DBusInterface], - Signals: { - 'closed': { - flags: GObject.SignalFlags.RUN_FIRST, - }, - }, -}, class RemoteSession extends Gio.DBusProxy { - - _init(objectPath) { - super._init({ - g_bus_type: Gio.BusType.SESSION, - g_name: 'org.gnome.Mutter.RemoteDesktop', - g_object_path: objectPath, - g_interface_name: 'org.gnome.Mutter.RemoteDesktop.Session', - g_flags: Gio.DBusProxyFlags.NONE, - }); - - this._started = false; - } - - vfunc_g_signal(sender_name, signal_name, parameters) { - if (signal_name === 'Closed') - this.emit('closed'); - } - - _call(name, parameters = null) { - if (!this._started) - return; - - // Pass a null callback to allow this call to finish itself - this.call(name, parameters, Gio.DBusCallFlags.NONE, -1, null, null); - } - - get session_id() { - try { - return this.get_cached_property('SessionId').unpack(); - } catch (e) { - return null; - } - } - - async start() { - try { - if (this._started) - return; - - // Initialize the proxy, and start the session - await this.init_async(GLib.PRIORITY_DEFAULT, null); - await this.call('Start', null, Gio.DBusCallFlags.NONE, -1, null); - - this._started = true; - } catch (e) { - this.destroy(); - - Gio.DBusError.strip_remote_error(e); - throw e; - } - } - - stop() { - if (this._started) { - this._started = false; - - // Pass a null callback to allow this call to finish itself - this.call('Stop', null, Gio.DBusCallFlags.NONE, -1, null, null); - } - } - - _translateButton(button) { - switch (button) { - case Gdk.BUTTON_PRIMARY: - return 0x110; - - case Gdk.BUTTON_MIDDLE: - return 0x112; - - case Gdk.BUTTON_SECONDARY: - return 0x111; - - case 4: - return 0; // FIXME - - case 5: - return 0x10F; // up - } - } - - movePointer(dx, dy) { - this._call( - 'NotifyPointerMotionRelative', - GLib.Variant.new('(dd)', [dx, dy]) - ); - } - - pressPointer(button) { - button = this._translateButton(button); - - this._call( - 'NotifyPointerButton', - GLib.Variant.new('(ib)', [button, true]) - ); - } - - releasePointer(button) { - button = this._translateButton(button); - - this._call( - 'NotifyPointerButton', - GLib.Variant.new('(ib)', [button, false]) - ); - } - - clickPointer(button) { - button = this._translateButton(button); - - this._call( - 'NotifyPointerButton', - GLib.Variant.new('(ib)', [button, true]) - ); - - this._call( - 'NotifyPointerButton', - GLib.Variant.new('(ib)', [button, false]) - ); - } - - doubleclickPointer(button) { - this.clickPointer(button); - this.clickPointer(button); - } - - scrollPointer(dx, dy) { - if (dy > 0) { - this._call( - 'NotifyPointerAxisDiscrete', - GLib.Variant.new('(ui)', [Gdk.ScrollDirection.UP, 1]) - ); - } else if (dy < 0) { - this._call( - 'NotifyPointerAxisDiscrete', - GLib.Variant.new('(ui)', [Gdk.ScrollDirection.UP, -1]) - ); - } - } - - /* - * Keyboard Events - */ - pressKeysym(keysym) { - this._call( - 'NotifyKeyboardKeysym', - GLib.Variant.new('(ub)', [keysym, true]) - ); - } - - releaseKeysym(keysym) { - this._call( - 'NotifyKeyboardKeysym', - GLib.Variant.new('(ub)', [keysym, false]) - ); - } - - pressreleaseKeysym(keysym) { - this._call( - 'NotifyKeyboardKeysym', - GLib.Variant.new('(ub)', [keysym, true]) - ); - this._call( - 'NotifyKeyboardKeysym', - GLib.Variant.new('(ub)', [keysym, false]) - ); - } - - /* - * High-level keyboard input - */ - pressKey(input, modifiers) { - // Press Modifiers - if (modifiers & Gdk.ModifierType.MOD1_MASK) - this.pressKeysym(Gdk.KEY_Alt_L); - if (modifiers & Gdk.ModifierType.CONTROL_MASK) - this.pressKeysym(Gdk.KEY_Control_L); - if (modifiers & Gdk.ModifierType.SHIFT_MASK) - this.pressKeysym(Gdk.KEY_Shift_L); - if (modifiers & Gdk.ModifierType.SUPER_MASK) - this.pressKeysym(Gdk.KEY_Super_L); - - if (typeof input === 'string') { - const keysym = Gdk.unicode_to_keyval(input.codePointAt(0)); - this.pressreleaseKeysym(keysym); - } else { - this.pressreleaseKeysym(input); - } - - // Release Modifiers - if (modifiers & Gdk.ModifierType.MOD1_MASK) - this.releaseKeysym(Gdk.KEY_Alt_L); - if (modifiers & Gdk.ModifierType.CONTROL_MASK) - this.releaseKeysym(Gdk.KEY_Control_L); - if (modifiers & Gdk.ModifierType.SHIFT_MASK) - this.releaseKeysym(Gdk.KEY_Shift_L); - if (modifiers & Gdk.ModifierType.SUPER_MASK) - this.releaseKeysym(Gdk.KEY_Super_L); - } - - destroy() { - if (this.__disposed === undefined) { - this.__disposed = true; - GObject.signal_handlers_destroy(this); - } - } -}); - - -export default class Controller { - constructor() { - this._nameAppearedId = 0; - this._session = null; - this._sessionCloseId = 0; - this._sessionExpiry = 0; - this._sessionExpiryId = 0; - this._sessionStarting = false; - - // Watch for the RemoteDesktop portal - this._nameWatcherId = Gio.bus_watch_name( - Gio.BusType.SESSION, - 'org.gnome.Mutter.RemoteDesktop', - Gio.BusNameWatcherFlags.NONE, - this._onNameAppeared.bind(this), - this._onNameVanished.bind(this) - ); - } - - get connection() { - if (this._connection === undefined) - this._connection = null; - - return this._connection; - } - - _onNameAppeared(connection, name, name_owner) { - try { - this._connection = connection; - } catch (e) { - logError(e); - } - } - - _onNameVanished(connection, name) { - try { - if (this._session !== null) - this._onSessionClosed(this._session); - } catch (e) { - logError(e); - } - } - - _onSessionClosed(session) { - // Disconnect from the session - if (this._sessionClosedId > 0) { - session.disconnect(this._sessionClosedId); - this._sessionClosedId = 0; - } - - // Destroy the session - session.destroy(); - this._session = null; - } - - _onSessionExpired() { - // If the session has been used recently, schedule a new expiry - const remainder = Math.floor(this._sessionExpiry - (Date.now() / 1000)); - - if (remainder > 0) { - this._sessionExpiryId = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, - remainder, - this._onSessionExpired.bind(this) - ); - - return GLib.SOURCE_REMOVE; - } - - // Otherwise if there's an active session, close it - if (this._session !== null) - this._session.stop(); - - // Reset the GSource Id - this._sessionExpiryId = 0; - - return GLib.SOURCE_REMOVE; - } - - async _createRemoteDesktopSession() { - if (this.connection === null) - return Promise.reject(new Error('No DBus connection')); - - const reply = await this.connection.call( - 'org.gnome.Mutter.RemoteDesktop', - '/org/gnome/Mutter/RemoteDesktop', - 'org.gnome.Mutter.RemoteDesktop', - 'CreateSession', - null, - null, - Gio.DBusCallFlags.NONE, - -1, - null); - - return reply.deepUnpack()[0]; - } - - async _ensureAdapter() { - try { - // Update the timestamp of the last event - this._sessionExpiry = Math.floor((Date.now() / 1000) + SESSION_TIMEOUT); - - // Session is active - if (this._session !== null) - return; - - // Mutter's RemoteDesktop is not available, fall back to Atspi - if (this.connection === null) { - debug('Falling back to Atspi'); - - this._session = new AtspiController(); - - // Mutter is available and there isn't another session starting - } else if (this._sessionStarting === false) { - this._sessionStarting = true; - - debug('Creating Mutter RemoteDesktop session'); - - // This takes three steps: creating the remote desktop session, - // starting the session, and creating a screencast session for - // the remote desktop session. - const objectPath = await this._createRemoteDesktopSession(); - - this._session = new RemoteSession(objectPath); - await this._session.start(); - - // Watch for the session ending - this._sessionClosedId = this._session.connect( - 'closed', - this._onSessionClosed.bind(this) - ); - - if (this._sessionExpiryId === 0) { - this._sessionExpiryId = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, - SESSION_TIMEOUT, - this._onSessionExpired.bind(this) - ); - } - - this._sessionStarting = false; - } - } catch (e) { - logError(e); - - if (this._session !== null) { - this._session.destroy(); - this._session = null; - } - - this._sessionStarting = false; - } - } - - /* - * Pointer Events - */ - movePointer(dx, dy) { - try { - if (dx === 0 && dy === 0) - return; - - this._ensureAdapter(); - this._session.movePointer(dx, dy); - } catch (e) { - debug(e); - } - } - - pressPointer(button) { - try { - this._ensureAdapter(); - this._session.pressPointer(button); - } catch (e) { - debug(e); - } - } - - releasePointer(button) { - try { - this._ensureAdapter(); - this._session.releasePointer(button); - } catch (e) { - debug(e); - } - } - - clickPointer(button) { - try { - this._ensureAdapter(); - this._session.clickPointer(button); - } catch (e) { - debug(e); - } - } - - doubleclickPointer(button) { - try { - this._ensureAdapter(); - this._session.doubleclickPointer(button); - } catch (e) { - debug(e); - } - } - - scrollPointer(dx, dy) { - if (dx === 0 && dy === 0) - return; - - try { - this._ensureAdapter(); - this._session.scrollPointer(dx, dy); - } catch (e) { - debug(e); - } - } - - /* - * Keyboard Events - */ - pressKeysym(keysym) { - try { - this._ensureAdapter(); - this._session.pressKeysym(keysym); - } catch (e) { - debug(e); - } - } - - releaseKeysym(keysym) { - try { - this._ensureAdapter(); - this._session.releaseKeysym(keysym); - } catch (e) { - debug(e); - } - } - - pressreleaseKeysym(keysym) { - try { - this._ensureAdapter(); - this._session.pressreleaseKeysym(keysym); - } catch (e) { - debug(e); - } - } - - /* - * High-level keyboard input - */ - pressKeys(input, modifiers) { - try { - this._ensureAdapter(); - - if (typeof input === 'string') { - for (let i = 0; i < input.length; i++) - this._session.pressKey(input[i], modifiers); - } else { - this._session.pressKey(input, modifiers); - } - } catch (e) { - debug(e); - } - } - - destroy() { - if (this._session !== null) { - // Disconnect from the session - if (this._sessionClosedId > 0) { - this._session.disconnect(this._sessionClosedId); - this._sessionClosedId = 0; - } - - this._session.destroy(); - this._session = null; - } - - if (this._nameWatcherId > 0) { - Gio.bus_unwatch_name(this._nameWatcherId); - this._nameWatcherId = 0; - } - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/mpris.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/mpris.js deleted file mode 100755 index 70c42255..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/mpris.js +++ /dev/null @@ -1,1003 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - - -export const Player = GObject.registerClass({ - GTypeName: 'GSConnectMediaPlayerInterface', - Properties: { - // Application Properties - 'CanQuit': GObject.ParamSpec.boolean( - 'CanQuit', - 'Can Quit', - 'Whether the client can call the Quit method.', - GObject.ParamFlags.READABLE, - false - ), - 'Fullscreen': GObject.ParamSpec.boolean( - 'Fullscreen', - 'Fullscreen', - 'Whether the player is in fullscreen mode.', - GObject.ParamFlags.READWRITE, - false - ), - 'CanSetFullscreen': GObject.ParamSpec.boolean( - 'CanSetFullscreen', - 'Can Set Fullscreen', - 'Whether the client can set the Fullscreen property.', - GObject.ParamFlags.READABLE, - false - ), - 'CanRaise': GObject.ParamSpec.boolean( - 'CanRaise', - 'Can Raise', - 'Whether the client can call the Raise method.', - GObject.ParamFlags.READABLE, - false - ), - 'HasTrackList': GObject.ParamSpec.boolean( - 'HasTrackList', - 'Has Track List', - 'Whether the player has a track list.', - GObject.ParamFlags.READABLE, - false - ), - 'Identity': GObject.ParamSpec.string( - 'Identity', - 'Identity', - 'The application name.', - GObject.ParamFlags.READABLE, - null - ), - 'DesktopEntry': GObject.ParamSpec.string( - 'DesktopEntry', - 'DesktopEntry', - 'The basename of an installed .desktop file.', - GObject.ParamFlags.READABLE, - null - ), - 'SupportedUriSchemes': GObject.param_spec_variant( - 'SupportedUriSchemes', - 'Supported URI Schemes', - 'The URI schemes supported by the media player.', - new GLib.VariantType('as'), - null, - GObject.ParamFlags.READABLE - ), - 'SupportedMimeTypes': GObject.param_spec_variant( - 'SupportedMimeTypes', - 'Supported MIME Types', - 'The mime-types supported by the media player.', - new GLib.VariantType('as'), - null, - GObject.ParamFlags.READABLE - ), - - // Player Properties - 'PlaybackStatus': GObject.ParamSpec.string( - 'PlaybackStatus', - 'Playback Status', - 'The current playback status.', - GObject.ParamFlags.READABLE, - null - ), - 'LoopStatus': GObject.ParamSpec.string( - 'LoopStatus', - 'Loop Status', - 'The current loop status.', - GObject.ParamFlags.READWRITE, - null - ), - 'Rate': GObject.ParamSpec.double( - 'Rate', - 'Rate', - 'The current playback rate.', - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 1.0 - ), - 'MinimumRate': GObject.ParamSpec.double( - 'MinimumRate', - 'Minimum Rate', - 'The minimum playback rate.', - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 1.0 - ), - 'MaximimRate': GObject.ParamSpec.double( - 'MaximumRate', - 'Maximum Rate', - 'The maximum playback rate.', - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 1.0 - ), - 'Shuffle': GObject.ParamSpec.boolean( - 'Shuffle', - 'Shuffle', - 'Whether track changes are linear.', - GObject.ParamFlags.READWRITE, - null - ), - 'Metadata': GObject.param_spec_variant( - 'Metadata', - 'Metadata', - 'The metadata of the current element.', - new GLib.VariantType('a{sv}'), - null, - GObject.ParamFlags.READABLE - ), - 'Volume': GObject.ParamSpec.double( - 'Volume', - 'Volume', - 'The volume level.', - GObject.ParamFlags.READWRITE, - 0.0, 1.0, - 1.0 - ), - 'Position': GObject.ParamSpec.int64( - 'Position', - 'Position', - 'The current track position in microseconds.', - GObject.ParamFlags.READABLE, - 0, Number.MAX_SAFE_INTEGER, - 0 - ), - 'CanGoNext': GObject.ParamSpec.boolean( - 'CanGoNext', - 'Can Go Next', - 'Whether the client can call the Next method.', - GObject.ParamFlags.READABLE, - false - ), - 'CanGoPrevious': GObject.ParamSpec.boolean( - 'CanGoPrevious', - 'Can Go Previous', - 'Whether the client can call the Previous method.', - GObject.ParamFlags.READABLE, - false - ), - 'CanPlay': GObject.ParamSpec.boolean( - 'CanPlay', - 'Can Play', - 'Whether playback can be started using Play or PlayPause.', - GObject.ParamFlags.READABLE, - false - ), - 'CanPause': GObject.ParamSpec.boolean( - 'CanPause', - 'Can Pause', - 'Whether playback can be paused using Play or PlayPause.', - GObject.ParamFlags.READABLE, - false - ), - 'CanSeek': GObject.ParamSpec.boolean( - 'CanSeek', - 'Can Seek', - 'Whether the client can control the playback position using Seek and SetPosition.', - GObject.ParamFlags.READABLE, - false - ), - 'CanControl': GObject.ParamSpec.boolean( - 'CanControl', - 'Can Control', - 'Whether the media player may be controlled over this interface.', - GObject.ParamFlags.READABLE, - false - ), - }, - Signals: { - 'Seeked': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [GObject.TYPE_INT64], - }, - }, -}, class Player extends GObject.Object { - - /* - * The org.mpris.MediaPlayer2 Interface - */ - get CanQuit() { - if (this._CanQuit === undefined) - this._CanQuit = false; - - return this._CanQuit; - } - - get CanRaise() { - if (this._CanRaise === undefined) - this._CanRaise = false; - - return this._CanRaise; - } - - get CanSetFullscreen() { - if (this._CanFullscreen === undefined) - this._CanFullscreen = false; - - return this._CanFullscreen; - } - - get DesktopEntry() { - if (this._DesktopEntry === undefined) - return 'org.gnome.Shell.Extensions.GSConnect'; - - return this._DesktopEntry; - } - - get Fullscreen() { - if (this._Fullscreen === undefined) - this._Fullscreen = false; - - return this._Fullscreen; - } - - set Fullscreen(mode) { - if (this.Fullscreen === mode) - return; - - this._Fullscreen = mode; - this.notify('Fullscreen'); - } - - get HasTrackList() { - if (this._HasTrackList === undefined) - this._HasTrackList = false; - - return this._HasTrackList; - } - - get Identity() { - if (this._Identity === undefined) - this._Identity = ''; - - return this._Identity; - } - - get SupportedMimeTypes() { - if (this._SupportedMimeTypes === undefined) - this._SupportedMimeTypes = []; - - return this._SupportedMimeTypes; - } - - get SupportedUriSchemes() { - if (this._SupportedUriSchemes === undefined) - this._SupportedUriSchemes = []; - - return this._SupportedUriSchemes; - } - - Quit() { - throw new GObject.NotImplementedError(); - } - - Raise() { - throw new GObject.NotImplementedError(); - } - - /* - * The org.mpris.MediaPlayer2.Player Interface - */ - get CanControl() { - if (this._CanControl === undefined) - this._CanControl = false; - - return this._CanControl; - } - - get CanGoNext() { - if (this._CanGoNext === undefined) - this._CanGoNext = false; - - return this._CanGoNext; - } - - get CanGoPrevious() { - if (this._CanGoPrevious === undefined) - this._CanGoPrevious = false; - - return this._CanGoPrevious; - } - - get CanPause() { - if (this._CanPause === undefined) - this._CanPause = false; - - return this._CanPause; - } - - get CanPlay() { - if (this._CanPlay === undefined) - this._CanPlay = false; - - return this._CanPlay; - } - - get CanSeek() { - if (this._CanSeek === undefined) - this._CanSeek = false; - - return this._CanSeek; - } - - get LoopStatus() { - if (this._LoopStatus === undefined) - this._LoopStatus = 'None'; - - return this._LoopStatus; - } - - set LoopStatus(status) { - if (this.LoopStatus === status) - return; - - this._LoopStatus = status; - this.notify('LoopStatus'); - } - - get MaximumRate() { - if (this._MaximumRate === undefined) - this._MaximumRate = 1.0; - - return this._MaximumRate; - } - - get Metadata() { - if (this._Metadata === undefined) { - this._Metadata = { - 'xesam:artist': [_('Unknown')], - 'xesam:album': _('Unknown'), - 'xesam:title': _('Unknown'), - 'mpris:length': 0, - }; - } - - return this._Metadata; - } - - get MinimumRate() { - if (this._MinimumRate === undefined) - this._MinimumRate = 1.0; - - return this._MinimumRate; - } - - get PlaybackStatus() { - if (this._PlaybackStatus === undefined) - this._PlaybackStatus = 'Stopped'; - - return this._PlaybackStatus; - } - - get Position() { - if (this._Position === undefined) - this._Position = 0; - - return this._Position; - } - - get Rate() { - if (this._Rate === undefined) - this._Rate = 1.0; - - return this._Rate; - } - - set Rate(rate) { - if (this.Rate === rate) - return; - - this._Rate = rate; - this.notify('Rate'); - } - - get Shuffle() { - if (this._Shuffle === undefined) - this._Shuffle = false; - - return this._Shuffle; - } - - set Shuffle(mode) { - if (this.Shuffle === mode) - return; - - this._Shuffle = mode; - this.notify('Shuffle'); - } - - get Volume() { - if (this._Volume === undefined) - this._Volume = 1.0; - - return this._Volume; - } - - set Volume(level) { - if (this.Volume === level) - return; - - this._Volume = level; - this.notify('Volume'); - } - - Next() { - throw new GObject.NotImplementedError(); - } - - OpenUri(uri) { - throw new GObject.NotImplementedError(); - } - - Previous() { - throw new GObject.NotImplementedError(); - } - - Pause() { - throw new GObject.NotImplementedError(); - } - - Play() { - throw new GObject.NotImplementedError(); - } - - PlayPause() { - throw new GObject.NotImplementedError(); - } - - Seek(offset) { - throw new GObject.NotImplementedError(); - } - - SetPosition(trackId, position) { - throw new GObject.NotImplementedError(); - } - - Stop() { - throw new GObject.NotImplementedError(); - } -}); - - -/** - * An aggregate of the org.mpris.MediaPlayer2 and org.mpris.MediaPlayer2.Player - * interfaces. - */ -const PlayerProxy = GObject.registerClass({ - GTypeName: 'GSConnectMPRISPlayer', -}, class PlayerProxy extends Player { - - _init(name) { - super._init(); - - this._application = new Gio.DBusProxy({ - g_bus_type: Gio.BusType.SESSION, - g_name: name, - g_object_path: '/org/mpris/MediaPlayer2', - g_interface_name: 'org.mpris.MediaPlayer2', - }); - - this._applicationChangedId = this._application.connect( - 'g-properties-changed', - this._onPropertiesChanged.bind(this) - ); - - this._player = new Gio.DBusProxy({ - g_bus_type: Gio.BusType.SESSION, - g_name: name, - g_object_path: '/org/mpris/MediaPlayer2', - g_interface_name: 'org.mpris.MediaPlayer2.Player', - }); - - this._playerChangedId = this._player.connect( - 'g-properties-changed', - this._onPropertiesChanged.bind(this) - ); - - this._playerSignalId = this._player.connect( - 'g-signal', - this._onSignal.bind(this) - ); - - this._cancellable = new Gio.Cancellable(); - } - - _onSignal(proxy, sender_name, signal_name, parameters) { - try { - if (signal_name !== 'Seeked') - return; - - this.emit('Seeked', parameters.deepUnpack()[0]); - } catch (e) { - debug(e, proxy.g_name); - } - } - - _call(proxy, name, parameters = null) { - proxy.call( - name, - parameters, - Gio.DBusCallFlags.NO_AUTO_START, - -1, - this._cancellable, - (proxy, result) => { - try { - proxy.call_finish(result); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - debug(e, proxy.g_name); - } - } - ); - } - - _get(proxy, name, fallback = null) { - try { - return proxy.get_cached_property(name).recursiveUnpack(); - } catch (e) { - return fallback; - } - } - - _set(proxy, name, value) { - try { - proxy.set_cached_property(name, value); - - proxy.call( - 'org.freedesktop.DBus.Properties.Set', - new GLib.Variant('(ssv)', [proxy.g_interface_name, name, value]), - Gio.DBusCallFlags.NO_AUTO_START, - -1, - this._cancellable, - (proxy, result) => { - try { - proxy.call_finish(result); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - debug(e, proxy.g_name); - } - } - ); - } catch (e) { - debug(e, proxy.g_name); - } - } - - _onPropertiesChanged(proxy, changed, invalidated) { - try { - this.freeze_notify(); - - for (const name in changed.deepUnpack()) - this.notify(name); - - this.thaw_notify(); - } catch (e) { - debug(e, proxy.g_name); - } - } - - /* - * The org.mpris.MediaPlayer2 Interface - */ - get CanQuit() { - return this._get(this._application, 'CanQuit', false); - } - - get CanRaise() { - return this._get(this._application, 'CanRaise', false); - } - - get CanSetFullscreen() { - return this._get(this._application, 'CanSetFullscreen', false); - } - - get DesktopEntry() { - return this._get(this._application, 'DesktopEntry', null); - } - - get Fullscreen() { - return this._get(this._application, 'Fullscreen', false); - } - - set Fullscreen(mode) { - this._set(this._application, 'Fullscreen', new GLib.Variant('b', mode)); - } - - get HasTrackList() { - return this._get(this._application, 'HasTrackList', false); - } - - get Identity() { - return this._get(this._application, 'Identity', _('Unknown')); - } - - get SupportedMimeTypes() { - return this._get(this._application, 'SupportedMimeTypes', []); - } - - get SupportedUriSchemes() { - return this._get(this._application, 'SupportedUriSchemes', []); - } - - Quit() { - this._call(this._application, 'Quit'); - } - - Raise() { - this._call(this._application, 'Raise'); - } - - /* - * The org.mpris.MediaPlayer2.Player Interface - */ - get CanControl() { - return this._get(this._player, 'CanControl', false); - } - - get CanGoNext() { - return this._get(this._player, 'CanGoNext', false); - } - - get CanGoPrevious() { - return this._get(this._player, 'CanGoPrevious', false); - } - - get CanPause() { - return this._get(this._player, 'CanPause', false); - } - - get CanPlay() { - return this._get(this._player, 'CanPlay', false); - } - - get CanSeek() { - return this._get(this._player, 'CanSeek', false); - } - - get LoopStatus() { - return this._get(this._player, 'LoopStatus', 'None'); - } - - set LoopStatus(status) { - this._set(this._player, 'LoopStatus', new GLib.Variant('s', status)); - } - - get MaximumRate() { - return this._get(this._player, 'MaximumRate', 1.0); - } - - get Metadata() { - if (this._metadata === undefined) { - this._metadata = { - 'xesam:artist': [_('Unknown')], - 'xesam:album': _('Unknown'), - 'xesam:title': _('Unknown'), - 'mpris:length': 0, - }; - } - - return this._get(this._player, 'Metadata', this._metadata); - } - - get MinimumRate() { - return this._get(this._player, 'MinimumRate', 1.0); - } - - get PlaybackStatus() { - return this._get(this._player, 'PlaybackStatus', 'Stopped'); - } - - // g-properties-changed is not emitted for this property - get Position() { - try { - const reply = this._player.call_sync( - 'org.freedesktop.DBus.Properties.Get', - new GLib.Variant('(ss)', [ - 'org.mpris.MediaPlayer2.Player', - 'Position', - ]), - Gio.DBusCallFlags.NONE, - -1, - null - ); - - return reply.recursiveUnpack()[0]; - } catch (e) { - return 0; - } - } - - get Rate() { - return this._get(this._player, 'Rate', 1.0); - } - - set Rate(rate) { - this._set(this._player, 'Rate', new GLib.Variant('d', rate)); - } - - get Shuffle() { - return this._get(this._player, 'Shuffle', false); - } - - set Shuffle(mode) { - this._set(this._player, 'Shuffle', new GLib.Variant('b', mode)); - } - - get Volume() { - return this._get(this._player, 'Volume', 1.0); - } - - set Volume(level) { - this._set(this._player, 'Volume', new GLib.Variant('d', level)); - } - - Next() { - this._call(this._player, 'Next'); - } - - OpenUri(uri) { - this._call(this._player, 'OpenUri', new GLib.Variant('(s)', [uri])); - } - - Previous() { - this._call(this._player, 'Previous'); - } - - Pause() { - this._call(this._player, 'Pause'); - } - - Play() { - this._call(this._player, 'Play'); - } - - PlayPause() { - this._call(this._player, 'PlayPause'); - } - - Seek(offset) { - this._call(this._player, 'Seek', new GLib.Variant('(x)', [offset])); - } - - SetPosition(trackId, position) { - this._call(this._player, 'SetPosition', - new GLib.Variant('(ox)', [trackId, position])); - } - - Stop() { - this._call(this._player, 'Stop'); - } - - destroy() { - if (this._cancellable.is_cancelled()) - return; - - this._cancellable.cancel(); - this._application.disconnect(this._applicationChangedId); - this._player.disconnect(this._playerChangedId); - this._player.disconnect(this._playerSignalId); - } -}); - - -/** - * A manager for media players - */ -const Manager = GObject.registerClass({ - GTypeName: 'GSConnectMPRISManager', - Signals: { - 'player-added': { - param_types: [GObject.TYPE_OBJECT], - }, - 'player-removed': { - param_types: [GObject.TYPE_OBJECT], - }, - 'player-changed': { - param_types: [GObject.TYPE_OBJECT], - }, - 'player-seeked': { - param_types: [GObject.TYPE_OBJECT, GObject.TYPE_INT64], - }, - }, -}, class Manager extends GObject.Object { - - _init() { - super._init(); - - // Asynchronous setup - this._cancellable = new Gio.Cancellable(); - this._connection = Gio.DBus.session; - this._players = new Map(); - this._paused = new Map(); - - this._nameOwnerChangedId = Gio.DBus.session.signal_subscribe( - 'org.freedesktop.DBus', - 'org.freedesktop.DBus', - 'NameOwnerChanged', - '/org/freedesktop/DBus', - 'org.mpris.MediaPlayer2', - Gio.DBusSignalFlags.MATCH_ARG0_NAMESPACE, - this._onNameOwnerChanged.bind(this) - ); - - this._loadPlayers(); - } - - async _loadPlayers() { - try { - const reply = await this._connection.call( - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus', - 'ListNames', - null, - null, - Gio.DBusCallFlags.NONE, - -1, - this._cancellable); - - const names = reply.deepUnpack()[0]; - - for (let i = 0, len = names.length; i < len; i++) { - const name = names[i]; - - if (!name.startsWith('org.mpris.MediaPlayer2')) - continue; - - if (!name.includes('GSConnect')) - this._addPlayer(name); - } - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } - } - - _onNameOwnerChanged(connection, sender, object, iface, signal, parameters) { - const [name, oldOwner, newOwner] = parameters.deepUnpack(); - - if (name.includes('GSConnect')) - return; - - if (newOwner.length) - this._addPlayer(name); - else if (oldOwner.length) - this._removePlayer(name); - } - - async _addPlayer(name) { - try { - if (!this._players.has(name)) { - const player = new PlayerProxy(name); - await Promise.all([ - player._application.init_async(GLib.PRIORITY_DEFAULT, - this._cancellable), - player._player.init_async(GLib.PRIORITY_DEFAULT, - this._cancellable), - ]); - - player.connect('notify', - (player) => this.emit('player-changed', player)); - - player.connect('Seeked', this.emit.bind(this, 'player-seeked')); - - this._players.set(name, player); - this.emit('player-added', player); - } - } catch (e) { - debug(e, name); - } - } - - _removePlayer(name) { - try { - const player = this._players.get(name); - - if (player !== undefined) { - this._paused.delete(name); - this._players.delete(name); - this.emit('player-removed', player); - - player.destroy(); - } - } catch (e) { - debug(e, name); - } - } - - /** - * Check for a player by its Identity. - * - * @param {string} identity - A player name - * @return {boolean} %true if the player was found - */ - hasPlayer(identity) { - for (const player of this._players.values()) { - if (player.Identity === identity) - return true; - } - - return false; - } - - /** - * Get a player by its Identity. - * - * @param {string} identity - A player name - * @return {GSConnectMPRISPlayer|null} A player or %null - */ - getPlayer(identity) { - for (const player of this._players.values()) { - if (player.Identity === identity) - return player; - } - - return null; - } - - /** - * Get a list of player identities. - * - * @return {string[]} A list of player identities - */ - getIdentities() { - const identities = []; - - for (const player of this._players.values()) { - const identity = player.Identity; - - if (identity) - identities.push(identity); - } - - return identities; - } - - /** - * A convenience function for pausing all players currently playing. - */ - pauseAll() { - for (const [name, player] of this._players) { - if (player.PlaybackStatus === 'Playing' && player.CanPause) { - player.Pause(); - this._paused.set(name, player); - } - } - } - - /** - * A convenience function for restarting all players paused with pauseAll(). - */ - unpauseAll() { - for (const player of this._paused.values()) { - if (player.PlaybackStatus === 'Paused' && player.CanPlay) - player.Play(); - } - - this._paused.clear(); - } - - destroy() { - if (this._cancellable.is_cancelled()) - return; - - this._cancellable.cancel(); - this._connection.signal_unsubscribe(this._nameOwnerChangedId); - - this._paused.clear(); - this._players.forEach(player => player.destroy()); - this._players.clear(); - } -}); - - -/** - * The service class for this component - */ -export default Manager; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/notification.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/notification.js deleted file mode 100755 index 0566a257..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/notification.js +++ /dev/null @@ -1,409 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GjsPrivate from 'gi://GjsPrivate'; -import GObject from 'gi://GObject'; - -import * as DBus from '../utils/dbus.js'; - - -const _nodeInfo = Gio.DBusNodeInfo.new_for_xml(` - - - - - - - - - - - - - - - - - - - - - - - - - -`); - - -const FDO_IFACE = _nodeInfo.lookup_interface('org.freedesktop.Notifications'); -const FDO_MATCH = "interface='org.freedesktop.Notifications',member='Notify',type='method_call'"; - -const GTK_IFACE = _nodeInfo.lookup_interface('org.gtk.Notifications'); -const GTK_MATCH = "interface='org.gtk.Notifications',member='AddNotification',type='method_call'"; - - -/** - * A class for snooping Freedesktop (libnotify) and Gtk (GNotification) - * notifications and forwarding them to supporting devices. - */ -const Listener = GObject.registerClass({ - GTypeName: 'GSConnectNotificationListener', - Signals: { - 'notification-added': { - flags: GObject.SignalFlags.RUN_LAST, - param_types: [GLib.Variant.$gtype], - }, - }, -}, class Listener extends GObject.Object { - - _init() { - super._init(); - - // Respect desktop notification settings - this._settings = new Gio.Settings({ - schema_id: 'org.gnome.desktop.notifications', - }); - - // Watch for new application policies - this._settingsId = this._settings.connect( - 'changed::application-children', - this._onSettingsChanged.bind(this) - ); - - // Cache for appName->desktop-id lookups - this._names = {}; - - // Asynchronous setup - this._init_async(); - } - - get applications() { - if (this._applications === undefined) - this._onSettingsChanged(); - - return this._applications; - } - - /** - * Update application notification settings - */ - _onSettingsChanged() { - this._applications = {}; - - for (const app of this._settings.get_strv('application-children')) { - const appSettings = new Gio.Settings({ - schema_id: 'org.gnome.desktop.notifications.application', - path: `/org/gnome/desktop/notifications/application/${app}/`, - }); - - const appInfo = Gio.DesktopAppInfo.new( - appSettings.get_string('application-id') - ); - - if (appInfo !== null) - this._applications[appInfo.get_name()] = appSettings; - } - } - - async _listNames() { - const reply = await this._session.call( - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus', - 'ListNames', - null, - null, - Gio.DBusCallFlags.NONE, - -1, - null); - - return reply.deepUnpack()[0]; - } - - async _getNameOwner(name) { - const reply = await this._session.call( - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus', - 'GetNameOwner', - new GLib.Variant('(s)', [name]), - null, - Gio.DBusCallFlags.NONE, - -1, - null); - - return reply.deepUnpack()[0]; - } - - /** - * Try and find a well-known name for @sender on the session bus - * - * @param {string} sender - A DBus unique name (eg. :1.2282) - * @param {string} appName - @appName passed to Notify() (Optional) - * @return {string} A well-known name or %null - */ - async _getAppId(sender, appName) { - try { - // Get a list of well-known names, ignoring @sender - const names = await this._listNames(); - names.splice(names.indexOf(sender), 1); - - // Make a short list for substring matches (fractal/org.gnome.Fractal) - const appLower = appName.toLowerCase(); - - const shortList = names.filter(name => { - return name.toLowerCase().includes(appLower); - }); - - // Run the short list first - for (const name of shortList) { - const nameOwner = await this._getNameOwner(name); - - if (nameOwner === sender) - return name; - - names.splice(names.indexOf(name), 1); - } - - // Run the full list - for (const name of names) { - const nameOwner = await this._getNameOwner(name); - - if (nameOwner === sender) - return name; - } - - return null; - } catch (e) { - debug(e); - return null; - } - } - - /** - * Try and find the application name for @sender - * - * @param {string} sender - A DBus unique name - * @param {string} [appName] - `appName` supplied by Notify() - * @return {string} A well-known name or %null - */ - async _getAppName(sender, appName = null) { - // Check the cache first - if (appName && this._names.hasOwnProperty(appName)) - return this._names[appName]; - - try { - const appId = await this._getAppId(sender, appName); - const appInfo = Gio.DesktopAppInfo.new(`${appId}.desktop`); - this._names[appName] = appInfo.get_name(); - appName = appInfo.get_name(); - } catch (e) { - // Silence errors - } - - return appName; - } - - /** - * Callback for AddNotification()/Notify() - * - * @param {DBus.Interface} iface - The DBus interface - * @param {string} name - The DBus method name - * @param {GLib.Variant} parameters - The method parameters - * @param {Gio.DBusMethodInvocation} invocation - The method invocation info - */ - async _onHandleMethodCall(iface, name, parameters, invocation) { - try { - // Check if notifications are disabled in desktop settings - if (!this._settings.get_boolean('show-banners')) - return; - - parameters = parameters.full_unpack(); - - // GNotification - if (name === 'AddNotification') { - this.AddNotification(...parameters); - - // libnotify - } else if (name === 'Notify') { - const message = invocation.get_message(); - const destination = message.get_destination(); - - // Deduplicate notifications; only accept messages - // directed to the notification bus, or its owner. - if (destination !== 'org.freedesktop.Notifications') { - if (this._fdoNameOwner === undefined) { - this._fdoNameOwner = await this._getNameOwner( - 'org.freedesktop.Notifications'); - } - - if (this._fdoNameOwner !== destination) - return; - } - - // Try to brute-force an application name using DBus - if (!this.applications.hasOwnProperty(parameters[0])) { - const sender = message.get_sender(); - parameters[0] = await this._getAppName(sender, parameters[0]); - } - - this.Notify(...parameters); - } - } catch (e) { - debug(e); - } - } - - /** - * Export interfaces for proxying notifications and become a monitor - * - * @return {Promise} A promise for the operation - */ - _monitorConnection() { - // libnotify Interface - this._fdoNotifications = new GjsPrivate.DBusImplementation({ - g_interface_info: FDO_IFACE, - }); - this._fdoMethodCallId = this._fdoNotifications.connect( - 'handle-method-call', this._onHandleMethodCall.bind(this)); - this._fdoNotifications.export(this._monitor, - '/org/freedesktop/Notifications'); - - this._fdoNameOwnerChangedId = this._session.signal_subscribe( - 'org.freedesktop.DBus', - 'org.freedesktop.DBus', - 'NameOwnerChanged', - '/org/freedesktop/DBus', - 'org.freedesktop.Notifications', - Gio.DBusSignalFlags.MATCH_ARG0_NAMESPACE, - this._onFdoNameOwnerChanged.bind(this) - ); - - // GNotification Interface - this._gtkNotifications = new GjsPrivate.DBusImplementation({ - g_interface_info: GTK_IFACE, - }); - this._gtkMethodCallId = this._gtkNotifications.connect( - 'handle-method-call', this._onHandleMethodCall.bind(this)); - this._gtkNotifications.export(this._monitor, '/org/gtk/Notifications'); - - // Become a monitor for Fdo & Gtk notifications - return this._monitor.call( - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - 'org.freedesktop.DBus.Monitoring', - 'BecomeMonitor', - new GLib.Variant('(asu)', [[FDO_MATCH, GTK_MATCH], 0]), - null, - Gio.DBusCallFlags.NONE, - -1, - null); - } - - async _init_async() { - try { - this._session = Gio.DBus.session; - this._monitor = await DBus.newConnection(); - await this._monitorConnection(); - } catch (e) { - const service = Gio.Application.get_default(); - - if (service !== null) - service.notify_error(e); - else - logError(e); - } - } - - _onFdoNameOwnerChanged(connection, sender, object, iface, signal, parameters) { - this._fdoNameOwner = parameters.deepUnpack()[2]; - } - - _sendNotification(notif) { - // Check if this application is disabled in desktop settings - const appSettings = this.applications[notif.appName]; - - if (appSettings && !appSettings.get_boolean('enable')) - return; - - // Send the notification to each supporting device - // TODO: avoid the overhead of the GAction framework with a signal? - const variant = GLib.Variant.full_pack(notif); - this.emit('notification-added', variant); - } - - Notify(appName, replacesId, iconName, summary, body, actions, hints, timeout) { - // Ignore notifications without an appName - if (!appName) - return; - - this._sendNotification({ - appName: appName, - id: `fdo|null|${replacesId}`, - title: summary, - text: body, - ticker: `${summary}: ${body}`, - isClearable: (replacesId !== 0), - icon: iconName, - }); - } - - AddNotification(application, id, notification) { - // Ignore our own notifications or we'll cause a notification loop - if (application === 'org.gnome.Shell.Extensions.GSConnect') - return; - - const appInfo = Gio.DesktopAppInfo.new(`${application}.desktop`); - - // Try to get an icon for the notification - if (!notification.hasOwnProperty('icon')) - notification.icon = appInfo.get_icon() || undefined; - - this._sendNotification({ - appName: appInfo.get_name(), - id: `gtk|${application}|${id}`, - title: notification.title, - text: notification.body, - ticker: `${notification.title}: ${notification.body}`, - isClearable: true, - icon: notification.icon, - }); - } - - destroy() { - try { - if (this._fdoNotifications) { - this._fdoNotifications.disconnect(this._fdoMethodCallId); - this._fdoNotifications.unexport(); - this._session.signal_unsubscribe(this._fdoNameOwnerChangedId); - } - - if (this._gtkNotifications) { - this._gtkNotifications.disconnect(this._gtkMethodCallId); - this._gtkNotifications.unexport(); - } - - if (this._settings) { - this._settings.disconnect(this._settingsId); - this._settings.run_dispose(); - } - - // TODO: Gio.IOErrorEnum: The connection is closed - // this._monitor.close_sync(null); - - GObject.signal_handlers_destroy(this); - } catch (e) { - debug(e); - } - } -}); - - -/** - * The service class for this component - */ -export default Listener; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js deleted file mode 100755 index 1165fc02..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GIRepository from 'gi://GIRepository'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../../config.js'; - -const Tweener = imports.tweener.tweener; - - -let Gvc = null; -try { - // Add gnome-shell's typelib dir to the search path - const typelibDir = GLib.build_filenamev([Config.GNOME_SHELL_LIBDIR, 'gnome-shell']); - GIRepository.Repository.prepend_search_path(typelibDir); - GIRepository.Repository.prepend_library_path(typelibDir); - - Gvc = (await import('gi://Gvc')).default; -} catch (e) {} - - -/** - * Extend Gvc.MixerStream with a property for returning a user-visible name - */ -if (Gvc) { - Object.defineProperty(Gvc.MixerStream.prototype, 'display_name', { - get: function () { - try { - if (!this.get_ports().length) - return this.description; - - return `${this.get_port().human_port} (${this.description})`; - } catch (e) { - return this.description; - } - }, - }); -} - - -/** - * A convenience wrapper for Gvc.MixerStream - */ -class Stream { - constructor(mixer, stream) { - this._mixer = mixer; - this._stream = stream; - - this._max = mixer.get_vol_max_norm(); - } - - get muted() { - return this._stream.is_muted; - } - - set muted(bool) { - this._stream.change_is_muted(bool); - } - - // Volume is a double in the range 0-1 - get volume() { - return Math.floor(100 * this._stream.volume / this._max) / 100; - } - - set volume(num) { - this._stream.volume = Math.floor(num * this._max); - this._stream.push_volume(); - } - - /** - * Gradually raise or lower the stream volume to @value - * - * @param {number} value - A number in the range 0-1 - * @param {number} [duration] - Duration to fade in seconds - */ - fade(value, duration = 1) { - Tweener.removeTweens(this); - - if (this._stream.volume > value) { - this._mixer.fading = true; - - Tweener.addTween(this, { - volume: value, - time: duration, - transition: 'easeOutCubic', - onComplete: () => { - this._mixer.fading = false; - }, - }); - } else if (this._stream.volume < value) { - this._mixer.fading = true; - - Tweener.addTween(this, { - volume: value, - time: duration, - transition: 'easeInCubic', - onComplete: () => { - this._mixer.fading = false; - }, - }); - } - } -} - - -/** - * A subclass of Gvc.MixerControl with convenience functions for controlling the - * default input/output volumes. - * - * The Mixer class uses GNOME Shell's Gvc library to control the system volume - * and offers a few convenience functions. - */ -const Mixer = !Gvc ? null : GObject.registerClass({ - GTypeName: 'GSConnectAudioMixer', -}, class Mixer extends Gvc.MixerControl { - _init(params) { - super._init({name: 'GSConnect'}); - - this._previousVolume = undefined; - this._volumeMuted = false; - this._microphoneMuted = false; - - this.open(); - } - - get fading() { - if (this._fading === undefined) - this._fading = false; - - return this._fading; - } - - set fading(bool) { - if (this.fading === bool) - return; - - this._fading = bool; - - if (this.fading) - this.emit('stream-changed', this._output._stream.id); - } - - get input() { - if (this._input === undefined) - this.vfunc_default_source_changed(); - - return this._input; - } - - get output() { - if (this._output === undefined) - this.vfunc_default_sink_changed(); - - return this._output; - } - - vfunc_default_sink_changed(id) { - try { - const sink = this.get_default_sink(); - this._output = (sink) ? new Stream(this, sink) : null; - } catch (e) { - logError(e); - } - } - - vfunc_default_source_changed(id) { - try { - const source = this.get_default_source(); - this._input = (source) ? new Stream(this, source) : null; - } catch (e) { - logError(e); - } - } - - vfunc_state_changed(new_state) { - try { - if (new_state === Gvc.MixerControlState.READY) { - this.vfunc_default_sink_changed(null); - this.vfunc_default_source_changed(null); - } - } catch (e) { - logError(e); - } - } - - /** - * Store the current output volume then lower it to %15 - * - * @param {number} duration - Duration in seconds to fade - */ - lowerVolume(duration = 1) { - try { - if (this.output && this.output.volume > 0.15) { - this._previousVolume = Number(this.output.volume); - this.output.fade(0.15, duration); - } - } catch (e) { - logError(e); - } - } - - /** - * Mute the output volume (speakers) - */ - muteVolume() { - try { - if (!this.output || this.output.muted) - return; - - this.output.muted = true; - this._volumeMuted = true; - } catch (e) { - logError(e); - } - } - - /** - * Mute the input volume (microphone) - */ - muteMicrophone() { - try { - if (!this.input || this.input.muted) - return; - - this.input.muted = true; - this._microphoneMuted = true; - } catch (e) { - logError(e); - } - } - - /** - * Restore all mixer levels to their previous state - */ - restore() { - try { - // If we muted the microphone, unmute it before restoring the volume - if (this._microphoneMuted) { - this.input.muted = false; - this._microphoneMuted = false; - } - - // If we muted the volume, unmute it before restoring the volume - if (this._volumeMuted) { - this.output.muted = false; - this._volumeMuted = false; - } - - // If a previous volume is defined, raise it back up to that level - if (this._previousVolume !== undefined) { - this.output.fade(this._previousVolume); - this._previousVolume = undefined; - } - } catch (e) { - logError(e); - } - } - - destroy() { - this.close(); - } -}); - - -/** - * The service class for this component - */ -export default Mixer; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/session.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/session.js deleted file mode 100755 index 5d574502..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/session.js +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - - -const Session = class { - constructor() { - this._connection = Gio.DBus.system; - this._session = null; - - this._initAsync(); - } - - async _initAsync() { - try { - const reply = await this._connection.call( - 'org.freedesktop.login1', - '/org/freedesktop/login1', - 'org.freedesktop.login1.Manager', - 'ListSessions', - null, - null, - Gio.DBusCallFlags.NONE, - -1, - null); - - const sessions = reply.deepUnpack()[0]; - const userName = GLib.get_user_name(); - let sessionPath = '/org/freedesktop/login1/session/auto'; - - // eslint-disable-next-line no-unused-vars - for (const [num, uid, name, seat, objectPath] of sessions) { - if (name === userName) { - sessionPath = objectPath; - break; - } - } - - this._session = new Gio.DBusProxy({ - g_connection: this._connection, - g_name: 'org.freedesktop.login1', - g_object_path: sessionPath, - g_interface_name: 'org.freedesktop.login1.Session', - }); - await this._session.init_async(GLib.PRIORITY_DEFAULT, null); - } catch (e) { - this._session = null; - logError(e); - } - } - - get idle() { - if (this._session === null) - return false; - - return this._session.get_cached_property('IdleHint').unpack(); - } - - get locked() { - if (this._session === null) - return false; - - return this._session.get_cached_property('LockedHint').unpack(); - } - - get active() { - // Active if not idle and not locked - return !(this.idle || this.locked); - } - - destroy() { - this._session = null; - } -}; - - -/** - * The service class for this component - */ -export default Session; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/sound.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/sound.js deleted file mode 100755 index 0845acfb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/sound.js +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - -let GSound = null; -try { - GSound = (await import('gi://GSound')).default; -} catch (e) {} - - -const Player = class Player { - - constructor() { - this._playing = new Set(); - } - - get backend() { - if (this._backend === undefined) { - // Prefer GSound - if (GSound !== null) { - this._gsound = new GSound.Context(); - this._gsound.init(null); - this._backend = 'gsound'; - - // Try falling back to libcanberra, otherwise just re-run the test - // in case one or the other is installed later - } else if (GLib.find_program_in_path('canberra-gtk-play') !== null) { - this._canberra = new Gio.SubprocessLauncher({ - flags: Gio.SubprocessFlags.NONE, - }); - this._backend = 'libcanberra'; - } else { - return null; - } - } - - return this._backend; - } - - _canberraPlaySound(name, cancellable) { - const proc = this._canberra.spawnv(['canberra-gtk-play', '-i', name]); - return proc.wait_check_async(cancellable); - } - - async _canberraLoopSound(name, cancellable) { - while (!cancellable.is_cancelled()) - await this._canberraPlaySound(name, cancellable); - } - - _gsoundPlaySound(name, cancellable) { - return new Promise((resolve, reject) => { - this._gsound.play_full( - {'event.id': name}, - cancellable, - (source, res) => { - try { - resolve(source.play_full_finish(res)); - } catch (e) { - reject(e); - } - } - ); - }); - } - - async _gsoundLoopSound(name, cancellable) { - while (!cancellable.is_cancelled()) - await this._gsoundPlaySound(name, cancellable); - } - - _gdkPlaySound(name, cancellable) { - if (this._display === undefined) - this._display = Gdk.Display.get_default(); - - let count = 0; - - GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => { - try { - if (count++ < 4 && !cancellable.is_cancelled()) { - this._display.beep(); - return GLib.SOURCE_CONTINUE; - } - - return GLib.SOURCE_REMOVE; - } catch (e) { - logError(e); - return GLib.SOURCE_REMOVE; - } - }); - - return !cancellable.is_cancelled(); - } - - _gdkLoopSound(name, cancellable) { - this._gdkPlaySound(name, cancellable); - GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - 1500, - this._gdkPlaySound.bind(this, name, cancellable) - ); - } - - async playSound(name, cancellable) { - try { - if (!(cancellable instanceof Gio.Cancellable)) - cancellable = new Gio.Cancellable(); - - this._playing.add(cancellable); - - switch (this.backend) { - case 'gsound': - await this._gsoundPlaySound(name, cancellable); - break; - - case 'canberra': - await this._canberraPlaySound(name, cancellable); - break; - - default: - await this._gdkPlaySound(name, cancellable); - } - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - this._playing.delete(cancellable); - } - } - - async loopSound(name, cancellable) { - try { - if (!(cancellable instanceof Gio.Cancellable)) - cancellable = new Gio.Cancellable(); - - this._playing.add(cancellable); - - switch (this.backend) { - case 'gsound': - await this._gsoundLoopSound(name, cancellable); - break; - - case 'canberra': - await this._canberraLoopSound(name, cancellable); - break; - - default: - await this._gdkLoopSound(name, cancellable); - } - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - } finally { - this._playing.delete(cancellable); - } - } - - destroy() { - for (const cancellable of this._playing) - cancellable.cancel(); - } -}; - - -/** - * The service class for this component - */ -export default Player; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/upower.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/upower.js deleted file mode 100755 index 722387b8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/upower.js +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - - -/** - * The warning level of a battery. - * - * @readonly - * @enum {number} - */ -const DeviceLevel = { - UNKNOWN: 0, - NONE: 1, - DISCHARGING: 2, - LOW: 3, - CRITICAL: 4, - ACTION: 5, - NORMAL: 6, - HIGH: 7, - FULL: 8, - LAST: 9, -}; - -/** - * The device state. - * - * @readonly - * @enum {number} - */ -const DeviceState = { - UNKNOWN: 0, - CHARGING: 1, - DISCHARGING: 2, - EMPTY: 3, - FULLY_CHARGED: 4, - PENDING_CHARGE: 5, - PENDING_DISCHARGE: 6, - LAST: 7, -}; - - -/** - * A class representing the system battery. - */ -const Battery = GObject.registerClass({ - GTypeName: 'GSConnectSystemBattery', - Signals: { - 'changed': { - flags: GObject.SignalFlags.RUN_FIRST, - }, - }, - Properties: { - 'charging': GObject.ParamSpec.boolean( - 'charging', - 'Charging', - 'The current charging state.', - GObject.ParamFlags.READABLE, - false - ), - 'level': GObject.ParamSpec.int( - 'level', - 'Level', - 'The current power level.', - GObject.ParamFlags.READABLE, - -1, 100, - -1 - ), - 'threshold': GObject.ParamSpec.uint( - 'threshold', - 'Threshold', - 'The current threshold state.', - GObject.ParamFlags.READABLE, - 0, 1, - 0 - ), - }, -}, class Battery extends GObject.Object { - - _init() { - super._init(); - - this._cancellable = new Gio.Cancellable(); - this._proxy = null; - this._propertiesChangedId = 0; - - this._loadUPower(); - } - - async _loadUPower() { - try { - this._proxy = new Gio.DBusProxy({ - g_bus_type: Gio.BusType.SYSTEM, - g_name: 'org.freedesktop.UPower', - g_object_path: '/org/freedesktop/UPower/devices/DisplayDevice', - g_interface_name: 'org.freedesktop.UPower.Device', - g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START, - }); - - await this._proxy.init_async(GLib.PRIORITY_DEFAULT, - this._cancellable); - - this._propertiesChangedId = this._proxy.connect( - 'g-properties-changed', this._onPropertiesChanged.bind(this)); - - this._initProperties(this._proxy); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - const service = Gio.Application.get_default(); - - if (service !== null) - service.notify_error(e); - else - logError(e); - } - - this._proxy = null; - } - } - - _initProperties(proxy) { - if (proxy.g_name_owner === null) - return; - - const percentage = proxy.get_cached_property('Percentage').unpack(); - const state = proxy.get_cached_property('State').unpack(); - const level = proxy.get_cached_property('WarningLevel').unpack(); - - this._level = Math.floor(percentage); - this._charging = (state !== DeviceState.DISCHARGING); - this._threshold = (!this.charging && level >= DeviceLevel.LOW); - - this.emit('changed'); - } - - _onPropertiesChanged(proxy, changed, invalidated) { - let emitChanged = false; - const properties = changed.deepUnpack(); - - if (properties.hasOwnProperty('Percentage')) { - emitChanged = true; - - const value = proxy.get_cached_property('Percentage').unpack(); - this._level = Math.floor(value); - this.notify('level'); - } - - if (properties.hasOwnProperty('State')) { - emitChanged = true; - - const value = proxy.get_cached_property('State').unpack(); - this._charging = (value !== DeviceState.DISCHARGING); - this.notify('charging'); - } - - if (properties.hasOwnProperty('WarningLevel')) { - emitChanged = true; - - const value = proxy.get_cached_property('WarningLevel').unpack(); - this._threshold = (!this.charging && value >= DeviceLevel.LOW); - this.notify('threshold'); - } - - if (emitChanged) - this.emit('changed'); - } - - get charging() { - if (this._charging === undefined) - this._charging = false; - - return this._charging; - } - - get is_present() { - return (this._proxy && this._proxy.g_name_owner); - } - - get level() { - if (this._level === undefined) - this._level = -1; - - return this._level; - } - - get threshold() { - if (this._threshold === undefined) - this._threshold = 0; - - return this._threshold; - } - - destroy() { - if (this._cancellable.is_cancelled()) - return; - - this._cancellable.cancel(); - - if (this._proxy && this._propertiesChangedId > 0) { - this._proxy.disconnect(this._propertiesChangedId); - this._propertiesChangedId = 0; - } - } -}); - - -/** - * The service class for this component - */ -export default Battery; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/ydotool.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/ydotool.js deleted file mode 100755 index de044185..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/components/ydotool.js +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-FileCopyrightText: JingMatrix https://github.com/JingMatrix -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import Gdk from 'gi://Gdk'; - -const keyCodes = new Map([ - ['1', 2], - ['2', 3], - ['3', 4], - ['4', 5], - ['5', 6], - ['6', 7], - ['7', 8], - ['8', 9], - ['9', 10], - ['0', 11], - ['-', 12], - ['=', 13], - ['Q', 16], - ['W', 17], - ['E', 18], - ['R', 19], - ['T', 20], - ['Y', 21], - ['U', 22], - ['I', 23], - ['O', 24], - ['P', 25], - ['[', 26], - [']', 27], - ['A', 30], - ['S', 31], - ['D', 32], - ['F', 33], - ['G', 34], - ['H', 35], - ['J', 36], - ['K', 37], - ['L', 38], - [';', 39], - ["'", 40], - ['Z', 44], - ['X', 45], - ['C', 46], - ['V', 47], - ['B', 48], - ['N', 49], - ['M', 50], - [',', 51], - ['.', 52], - ['/', 53], - ['\\', 43], -]); -export default class Controller { - constructor() { - // laucher for wl-clipboard - this._launcher = new Gio.SubprocessLauncher({ - flags: - Gio.SubprocessFlags.STDOUT_PIPE | - Gio.SubprocessFlags.STDERR_MERGE, - }); - this._args = []; - this.buttonMap = new Map([ - [Gdk.BUTTON_PRIMARY, '0'], - [Gdk.BUTTON_MIDDLE, '2'], - [Gdk.BUTTON_SECONDARY, '1'], - ]); - } - - get args() { - return this._args; - } - - set args(opts) { - this._args = ['ydotool'].concat(opts); - try { - this._launcher.spawnv(this._args); - } catch (e) { - debug(e, this._args); - } - } - - /* - * Pointer Events - */ - movePointer(dx, dy) { - if (dx === 0 && dy === 0) - return; - this.args = ['mousemove', '--', dx.toString(), dy.toString()]; - } - - pressPointer(button) { - this.args = ['click', '0x4' + this.buttonMap.get(button)]; - } - - releasePointer(button) { - this.args = ['click', '0x8' + this.buttonMap.get(button)]; - } - - clickPointer(button) { - this.args = ['click', '0xC' + this.buttonMap.get(button)]; - } - - doubleclickPointer(button) { - this.args = [ - 'click', - '0xC' + this.buttonMap.get(button), - 'click', - '0xC' + this.buttonMap.get(button), - ]; - } - - scrollPointer(dx, dy) { - if (dx === 0 && dy === 0) - return; - this.args = ['mousemove', '-w', '--', dx.toString(), dy.toString()]; - } - - /* - * Keyboard Events - */ - - pressKeys(input, modifiers_codes) { - if (typeof input === 'string' && modifiers_codes.length === 0) { - try { - this._launcher.spawnv(['wtype', input]); - } catch (e) { - debug(e); - this.arg = ['type', '--', input]; - } - } else { - if (typeof input === 'number') { - modifiers_codes.push(input); - } else if (typeof input === 'string') { - input = input.toUpperCase(); - for (let i = 0; i < input.length; i++) { - if (keyCodes.get(input[i])) { - modifiers_codes.push(keyCodes.get(input[i])); - } else { - debug('Keycode for ' + input[i] + ' not found'); - return; - } - } - - } - this._args = ['key']; - modifiers_codes.forEach((code) => this._args.push(code + ':1')); - modifiers_codes - .reverse() - .forEach((code) => this._args.push(code + ':0')); - this.args = this._args; - } - } - - destroy() { - this._args = []; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/core.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/core.js deleted file mode 100755 index 02b89bb6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/core.js +++ /dev/null @@ -1,694 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import plugins from './plugins/index.js'; - - -/** - * Get the local device type. - * - * @return {string} A device type string - */ -export function _getDeviceType() { - try { - let type = GLib.file_get_contents('/sys/class/dmi/id/chassis_type')[1]; - - type = Number(new TextDecoder().decode(type)); - - if ([8, 9, 10, 14].includes(type)) - return 'laptop'; - - return 'desktop'; - } catch (e) { - return 'desktop'; - } -} - - -/** - * The packet class is a simple Object-derived class, offering some conveniences - * for working with KDE Connect packets. - */ -export class Packet { - - constructor(data = null) { - this.id = 0; - this.type = undefined; - this.body = {}; - - if (typeof data === 'string') - Object.assign(this, JSON.parse(data)); - else if (data !== null) - Object.assign(this, data); - } - - [Symbol.toPrimitive](hint) { - this.id = Date.now(); - - if (hint === 'string') - return `${JSON.stringify(this)}\n`; - - if (hint === 'number') - return `${JSON.stringify(this)}\n`.length; - - return true; - } - - get [Symbol.toStringTag]() { - return `Packet:${this.type}`; - } - - /** - * Deserialize and return a new Packet from an Object or string. - * - * @param {Object|string} data - A string or dictionary to deserialize - * @return {Core.Packet} A new packet object - */ - static deserialize(data) { - return new Packet(data); - } - - /** - * Serialize the packet as a single line with a terminating new-line (`\n`) - * character, ready to be written to a channel. - * - * @return {string} A serialized packet - */ - serialize() { - this.id = Date.now(); - return `${JSON.stringify(this)}\n`; - } - - /** - * Update the packet from a dictionary or string of JSON - * - * @param {Object|string} data - Source data - */ - update(data) { - try { - if (typeof data === 'string') - Object.assign(this, JSON.parse(data)); - else - Object.assign(this, data); - } catch (e) { - throw Error(`Malformed data: ${e.message}`); - } - } - - /** - * Check if the packet has a payload. - * - * @return {boolean} %true if @packet has a payload - */ - hasPayload() { - if (!this.hasOwnProperty('payloadSize')) - return false; - - if (!this.hasOwnProperty('payloadTransferInfo')) - return false; - - return (Object.keys(this.payloadTransferInfo).length > 0); - } -} - - -/** - * Channel objects handle KDE Connect packet exchange and data transfers for - * devices. The implementation is responsible for all negotiation of the - * underlying protocol. - */ -export const Channel = GObject.registerClass({ - GTypeName: 'GSConnectChannel', - Properties: { - 'closed': GObject.ParamSpec.boolean( - 'closed', - 'Closed', - 'Whether the channel has been closed', - GObject.ParamFlags.READABLE, - false - ), - }, -}, class Channel extends GObject.Object { - - get address() { - throw new GObject.NotImplementedError(); - } - - get backend() { - if (this._backend === undefined) - this._backend = null; - - return this._backend; - } - - set backend(backend) { - this._backend = backend; - } - - get cancellable() { - if (this._cancellable === undefined) - this._cancellable = new Gio.Cancellable(); - - return this._cancellable; - } - - get closed() { - if (this._closed === undefined) - this._closed = false; - - return this._closed; - } - - get input_stream() { - if (this._input_stream === undefined) { - if (this._connection instanceof Gio.IOStream) - return this._connection.get_input_stream(); - - return null; - } - - return this._input_stream; - } - - set input_stream(stream) { - this._input_stream = stream; - } - - get output_stream() { - if (this._output_stream === undefined) { - if (this._connection instanceof Gio.IOStream) - return this._connection.get_output_stream(); - - return null; - } - - return this._output_stream; - } - - set output_stream(stream) { - this._output_stream = stream; - } - - get uuid() { - if (this._uuid === undefined) - this._uuid = GLib.uuid_string_random(); - - return this._uuid; - } - - set uuid(uuid) { - this._uuid = uuid; - } - - /** - * Close the channel. - */ - close() { - throw new GObject.NotImplementedError(); - } - - /** - * Read a packet. - * - * @param {Gio.Cancellable} [cancellable] - A cancellable - * @return {Promise} The packet - */ - async readPacket(cancellable = null) { - if (cancellable === null) - cancellable = this.cancellable; - - if (!(this.input_stream instanceof Gio.DataInputStream)) { - this.input_stream = new Gio.DataInputStream({ - base_stream: this.input_stream, - }); - } - - const [data] = await this.input_stream.read_line_async( - GLib.PRIORITY_DEFAULT, cancellable); - - if (data === null) { - throw new Gio.IOErrorEnum({ - message: 'End of stream', - code: Gio.IOErrorEnum.CONNECTION_CLOSED, - }); - } - - return new Packet(data); - } - - /** - * Send a packet. - * - * @param {Core.Packet} packet - The packet to send - * @param {Gio.Cancellable} [cancellable] - A cancellable - * @return {Promise} %true if successful - */ - sendPacket(packet, cancellable = null) { - if (cancellable === null) - cancellable = this.cancellable; - - return this.output_stream.write_all_async(packet.serialize(), - GLib.PRIORITY_DEFAULT, cancellable); - } - - /** - * Reject a transfer. - * - * @param {Core.Packet} packet - A packet with payload info - */ - rejectTransfer(packet) { - throw new GObject.NotImplementedError(); - } - - /** - * Download a payload from a device. Typically implementations will override - * this with an async function. - * - * @param {Core.Packet} packet - A packet - * @param {Gio.OutputStream} target - The target stream - * @param {Gio.Cancellable} [cancellable] - A cancellable for the upload - */ - download(packet, target, cancellable = null) { - throw new GObject.NotImplementedError(); - } - - - /** - * Upload a payload to a device. Typically implementations will override - * this with an async function. - * - * @param {Core.Packet} packet - The packet describing the transfer - * @param {Gio.InputStream} source - The source stream - * @param {number} size - The payload size - * @param {Gio.Cancellable} [cancellable] - A cancellable for the upload - */ - upload(packet, source, size, cancellable = null) { - throw new GObject.NotImplementedError(); - } -}); - - -/** - * ChannelService implementations provide Channel objects, emitting the - * ChannelService::channel signal when a new connection has been accepted. - */ -export const ChannelService = GObject.registerClass({ - GTypeName: 'GSConnectChannelService', - Properties: { - 'active': GObject.ParamSpec.boolean( - 'active', - 'Active', - 'Whether the service is active', - GObject.ParamFlags.READABLE, - false - ), - 'id': GObject.ParamSpec.string( - 'id', - 'ID', - 'The hostname or other network unique id', - GObject.ParamFlags.READWRITE, - null - ), - 'name': GObject.ParamSpec.string( - 'name', - 'Name', - 'The name of the backend', - GObject.ParamFlags.READWRITE, - null - ), - }, - Signals: { - 'channel': { - flags: GObject.SignalFlags.RUN_LAST, - param_types: [Channel.$gtype], - return_type: GObject.TYPE_BOOLEAN, - }, - }, -}, class ChannelService extends GObject.Object { - - get active() { - if (this._active === undefined) - this._active = false; - - return this._active; - } - - get cancellable() { - if (this._cancellable === undefined) - this._cancellable = new Gio.Cancellable(); - - return this._cancellable; - } - - get name() { - if (this._name === undefined) - this._name = GLib.get_host_name(); - - return this._name; - } - - set name(name) { - if (this.name === name) - return; - - this._name = name; - this.notify('name'); - } - - get id() { - if (this._id === undefined) - this._id = GLib.uuid_string_random(); - - return this._id; - } - - set id(id) { - if (this.id === id) - return; - - this._id = id; - } - - get identity() { - if (this._identity === undefined) - this.buildIdentity(); - - return this._identity; - } - - /** - * Broadcast directly to @address or the whole network if %null - * - * @param {string} [address] - A string address - */ - broadcast(address = null) { - throw new GObject.NotImplementedError(); - } - - /** - * Rebuild the identity packet used to identify the local device. An - * implementation may override this to make modifications to the default - * capabilities if necessary (eg. bluez without SFTP support). - */ - buildIdentity() { - this._identity = new Packet({ - id: 0, - type: 'kdeconnect.identity', - body: { - deviceId: this.id, - deviceName: this.name, - deviceType: _getDeviceType(), - protocolVersion: 7, - incomingCapabilities: [], - outgoingCapabilities: [], - }, - }); - - for (const name in plugins) { - const meta = plugins[name].Metadata; - - if (meta === undefined) - continue; - - for (const type of meta.incomingCapabilities) - this._identity.body.incomingCapabilities.push(type); - - for (const type of meta.outgoingCapabilities) - this._identity.body.outgoingCapabilities.push(type); - } - } - - /** - * Emit Core.ChannelService::channel - * - * @param {Core.Channel} channel - The new channel - */ - channel(channel) { - if (!this.emit('channel', channel)) - channel.close(); - } - - /** - * Start the channel service. Implementations should throw an error if the - * service fails to meet any of its requirements for opening or accepting - * connections. - */ - start() { - throw new GObject.NotImplementedError(); - } - - /** - * Stop the channel service. - */ - stop() { - throw new GObject.NotImplementedError(); - } - - /** - * Destroy the channel service. - */ - destroy() { - } -}); - - -/** - * A class representing a file transfer. - */ -export const Transfer = GObject.registerClass({ - GTypeName: 'GSConnectTransfer', - Properties: { - 'channel': GObject.ParamSpec.object( - 'channel', - 'Channel', - 'The channel that owns this transfer', - GObject.ParamFlags.READWRITE, - Channel.$gtype - ), - 'completed': GObject.ParamSpec.boolean( - 'completed', - 'Completed', - 'Whether the transfer has completed', - GObject.ParamFlags.READABLE, - false - ), - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device that created this transfer', - GObject.ParamFlags.READWRITE, - GObject.Object.$gtype - ), - }, -}, class Transfer extends GObject.Object { - - _init(params = {}) { - super._init(params); - - this._cancellable = new Gio.Cancellable(); - this._items = []; - } - - get channel() { - if (this._channel === undefined) - this._channel = null; - - return this._channel; - } - - set channel(channel) { - if (this.channel === channel) - return; - - this._channel = channel; - } - - get completed() { - if (this._completed === undefined) - this._completed = false; - - return this._completed; - } - - get device() { - if (this._device === undefined) - this._device = null; - - return this._device; - } - - set device(device) { - if (this.device === device) - return; - - this._device = device; - } - - get uuid() { - if (this._uuid === undefined) - this._uuid = GLib.uuid_string_random(); - - return this._uuid; - } - - /** - * Ensure there is a stream for the transfer item. - * - * @param {Object} item - A transfer item - * @param {Gio.Cancellable} [cancellable] - A cancellable - */ - async _ensureStream(item, cancellable = null) { - // This is an upload from a remote device - if (item.packet.hasPayload()) { - if (item.target instanceof Gio.OutputStream) - return; - - if (item.file instanceof Gio.File) { - item.target = await item.file.replace_async( - null, - false, - Gio.FileCreateFlags.REPLACE_DESTINATION, - GLib.PRIORITY_DEFAULT, - this._cancellable); - } - } else { - if (item.source instanceof Gio.InputStream) - return; - - if (item.file instanceof Gio.File) { - const read = item.file.read_async(GLib.PRIORITY_DEFAULT, - cancellable); - - const query = item.file.query_info_async( - Gio.FILE_ATTRIBUTE_STANDARD_SIZE, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, - cancellable); - - const [stream, info] = await Promise.all([read, query]); - item.source = stream; - item.size = info.get_size(); - } - } - } - - /** - * Add a file to the transfer. - * - * @param {Core.Packet} packet - A packet - * @param {Gio.File} file - A file to transfer - */ - addFile(packet, file) { - const item = { - packet: new Packet(packet), - file: file, - source: null, - target: null, - }; - - this._items.push(item); - } - - /** - * Add a filepath to the transfer. - * - * @param {Core.Packet} packet - A packet - * @param {string} path - A filepath to transfer - */ - addPath(packet, path) { - const item = { - packet: new Packet(packet), - file: Gio.File.new_for_path(path), - source: null, - target: null, - }; - - this._items.push(item); - } - - /** - * Add a stream to the transfer. - * - * @param {Core.Packet} packet - A packet - * @param {Gio.InputStream|Gio.OutputStream} stream - A stream to transfer - * @param {number} [size] - Payload size - */ - addStream(packet, stream, size = 0) { - const item = { - packet: new Packet(packet), - file: null, - source: null, - target: null, - size: size, - }; - - if (stream instanceof Gio.InputStream) - item.source = stream; - else if (stream instanceof Gio.OutputStream) - item.target = stream; - - this._items.push(item); - } - - /** - * Execute a transfer operation. Implementations may override this, while - * the default uses g_output_stream_splice(). - * - * @param {Gio.Cancellable} [cancellable] - A cancellable - */ - async start(cancellable = null) { - let error = null; - - try { - let item; - - // If a cancellable is passed in, chain to its signal - if (cancellable instanceof Gio.Cancellable) - cancellable.connect(() => this._cancellable.cancel()); - - while ((item = this._items.shift())) { - // If created for a device, ignore connection changes by - // ensuring we have the most recent channel - if (this.device !== null) - this._channel = this.device.channel; - - // TODO: transfer queueing? - if (this.channel === null || this.channel.closed) { - throw new Gio.IOErrorEnum({ - code: Gio.IOErrorEnum.CONNECTION_CLOSED, - message: 'Channel is closed', - }); - } - - await this._ensureStream(item, this._cancellable); - - if (item.packet.hasPayload()) { - await this.channel.download(item.packet, item.target, - this._cancellable); - } else { - await this.channel.upload(item.packet, item.source, - item.size, this._cancellable); - } - } - } catch (e) { - error = e; - } finally { - this._completed = true; - this.notify('completed'); - } - - if (error !== null) - throw error; - } - - cancel() { - if (this._cancellable.is_cancelled() === false) - this._cancellable.cancel(); - } -}); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/daemon.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/daemon.js deleted file mode 100755 index 1ddb3569..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/daemon.js +++ /dev/null @@ -1,702 +0,0 @@ -#!/usr/bin/env -S gjs -m - -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk?version=3.0'; -import 'gi://GdkPixbuf?version=2.0'; -import Gio from 'gi://Gio?version=2.0'; -import 'gi://GIRepository?version=2.0'; -import GLib from 'gi://GLib?version=2.0'; -import GObject from 'gi://GObject?version=2.0'; -import Gtk from 'gi://Gtk?version=3.0'; -import 'gi://Pango?version=1.0'; - -import system from 'system'; - -import './init.js'; - -import Config from '../config.js'; -import Manager from './manager.js'; -import * as ServiceUI from './ui/service.js'; - -import('gi://GioUnix?version=2.0').catch(() => {}); // Set version for optional dependency - - -/** - * Class representing the GSConnect service daemon. - */ -const Service = GObject.registerClass({ - GTypeName: 'GSConnectService', -}, class Service extends Gtk.Application { - - _init() { - super._init({ - application_id: 'org.gnome.Shell.Extensions.GSConnect', - flags: Gio.ApplicationFlags.HANDLES_OPEN, - resource_base_path: '/org/gnome/Shell/Extensions/GSConnect', - }); - - GLib.set_prgname('gsconnect'); - GLib.set_application_name('GSConnect'); - - // Command-line - this._initOptions(); - } - - get settings() { - if (this._settings === undefined) { - this._settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true), - }); - } - - return this._settings; - } - - /* - * GActions - */ - _initActions() { - const actions = [ - ['connect', this._identify.bind(this), new GLib.VariantType('s')], - ['device', this._device.bind(this), new GLib.VariantType('(ssbv)')], - ['error', this._error.bind(this), new GLib.VariantType('a{ss}')], - ['preferences', this._preferences, null], - ['quit', () => this.quit(), null], - ['refresh', this._identify.bind(this), null], - ]; - - for (const [name, callback, type] of actions) { - const action = new Gio.SimpleAction({ - name: name, - parameter_type: type, - }); - action.connect('activate', callback); - this.add_action(action); - } - } - - /** - * A wrapper for Device GActions. This is used to route device notification - * actions to their device, since GNotifications need an 'app' level action. - * - * @param {Gio.Action} action - The GAction - * @param {GLib.Variant} parameter - The activation parameter - */ - _device(action, parameter) { - try { - parameter = parameter.unpack(); - - // Select the appropriate device(s) - let devices; - const id = parameter[0].unpack(); - - if (id === '*') - devices = this.manager.devices.values(); - else - devices = [this.manager.devices.get(id)]; - - // Unpack the action data and activate the action - const name = parameter[1].unpack(); - const target = parameter[2].unpack() ? parameter[3].unpack() : null; - - for (const device of devices) - device.activate_action(name, target); - } catch (e) { - logError(e); - } - } - - _error(action, parameter) { - try { - const error = parameter.deepUnpack(); - - // If there's a URL, we have better information in the Wiki - if (error.url !== undefined) { - Gio.AppInfo.launch_default_for_uri_async( - error.url, - null, - null, - null - ); - return; - } - - const dialog = new ServiceUI.ErrorDialog(error); - dialog.present(); - } catch (e) { - logError(e); - } - } - - _identify(action, parameter) { - try { - let uri = null; - - if (parameter instanceof GLib.Variant) - uri = parameter.unpack(); - - this.manager.identify(uri); - } catch (e) { - logError(e); - } - } - - _preferences() { - Gio.Subprocess.new( - [`${Config.PACKAGE_DATADIR}/gsconnect-preferences`], - Gio.SubprocessFlags.NONE - ); - } - - /** - * Report a service-level error - * - * @param {Object} error - An Error or object with name, message and stack - */ - notify_error(error) { - try { - // Always log the error - logError(error); - - // Create an new notification - let id, body, priority; - const notif = new Gio.Notification(); - const icon = new Gio.ThemedIcon({name: 'dialog-error'}); - let target = null; - - if (error.name === undefined) - error.name = 'Error'; - - if (error.url !== undefined) { - id = error.url; - body = _('Click for help troubleshooting'); - priority = Gio.NotificationPriority.URGENT; - - target = new GLib.Variant('a{ss}', { - name: error.name.trim(), - message: error.message.trim(), - stack: error.stack.trim(), - url: error.url, - }); - } else { - id = error.message.trim(); - body = _('Click for more information'); - priority = Gio.NotificationPriority.HIGH; - - target = new GLib.Variant('a{ss}', { - name: error.name.trim(), - message: error.message.trim(), - stack: error.stack.trim(), - }); - } - - notif.set_title(`GSConnect: ${error.name.trim()}`); - notif.set_body(body); - notif.set_icon(icon); - notif.set_priority(priority); - notif.set_default_action_and_target('app.error', target); - - this.send_notification(id, notif); - } catch (e) { - logError(e); - } - } - - vfunc_activate() { - super.vfunc_activate(); - } - - vfunc_startup() { - super.vfunc_startup(); - - this.hold(); - - // Watch *this* file and stop the service if it's updated/uninstalled - this._serviceMonitor = Gio.File.new_for_path( - `${Config.PACKAGE_DATADIR}/service/daemon.js` - ).monitor(Gio.FileMonitorFlags.WATCH_MOVES, null); - this._serviceMonitor.connect('changed', () => this.quit()); - - // Init some resources - const provider = new Gtk.CssProvider(); - provider.load_from_resource(`${Config.APP_PATH}/application.css`); - Gtk.StyleContext.add_provider_for_screen( - Gdk.Screen.get_default(), - provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - // Ensure our handlers are registered - try { - const appInfo = Gio.DesktopAppInfo.new(`${Config.APP_ID}.desktop`); - appInfo.add_supports_type('x-scheme-handler/sms'); - appInfo.add_supports_type('x-scheme-handler/tel'); - } catch (e) { - debug(e); - } - - // GActions & GSettings - this._initActions(); - - this.manager.start(); - } - - vfunc_dbus_register(connection, object_path) { - if (!super.vfunc_dbus_register(connection, object_path)) - return false; - - this.manager = new Manager({ - connection: connection, - object_path: object_path, - }); - - return true; - } - - vfunc_dbus_unregister(connection, object_path) { - this.manager.destroy(); - - super.vfunc_dbus_unregister(connection, object_path); - } - - vfunc_open(files, hint) { - super.vfunc_open(files, hint); - - for (const file of files) { - let action, parameter, title; - - try { - switch (file.get_uri_scheme()) { - case 'sms': - title = _('Send SMS'); - action = 'uriSms'; - parameter = new GLib.Variant('s', file.get_uri()); - break; - - case 'tel': - title = _('Dial Number'); - action = 'shareUri'; - parameter = new GLib.Variant('s', file.get_uri()); - break; - - case 'file': - title = _('Share File'); - action = 'shareFile'; - parameter = new GLib.Variant('(sb)', [file.get_uri(), false]); - break; - - default: - throw new Error(`Unsupported URI: ${file.get_uri()}`); - } - - // Show chooser dialog - new ServiceUI.DeviceChooser({ - title: title, - action_name: action, - action_target: parameter, - }); - } catch (e) { - logError(e, `GSConnect: Opening ${file.get_uri()}`); - } - } - } - - vfunc_shutdown() { - // Dispose GSettings - if (this._settings !== undefined) - this.settings.run_dispose(); - - this.manager.stop(); - - // Exhaust the event loop to ensure any pending operations complete - const context = GLib.MainContext.default(); - - while (context.iteration(false)) - continue; - - // Force a GC to prevent any more calls back into JS, then chain-up - system.gc(); - super.vfunc_shutdown(); - } - - /* - * CLI - */ - _initOptions() { - /* - * Device Listings - */ - this.add_main_option( - 'list-devices', - 'l'.charCodeAt(0), - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('List available devices'), - null - ); - - this.add_main_option( - 'list-all', - 'a'.charCodeAt(0), - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('List all devices'), - null - ); - - this.add_main_option( - 'device', - 'd'.charCodeAt(0), - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Target Device'), - '' - ); - - /** - * Pairing - */ - this.add_main_option( - 'pair', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Pair'), - null - ); - - this.add_main_option( - 'unpair', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Unpair'), - null - ); - - /* - * Messaging - */ - this.add_main_option( - 'message', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING_ARRAY, - _('Send SMS'), - '' - ); - - this.add_main_option( - 'message-body', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Message Body'), - '' - ); - - /* - * Notifications - */ - this.add_main_option( - 'notification', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Send Notification'), - '' - ); - - this.add_main_option( - 'notification-appname', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Notification App Name'), - '<name>' - ); - - this.add_main_option( - 'notification-body', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Notification Body'), - '<text>' - ); - - this.add_main_option( - 'notification-icon', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Notification Icon'), - '<icon-name>' - ); - - this.add_main_option( - 'notification-id', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Notification ID'), - '<id>' - ); - - this.add_main_option( - 'ping', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Ping'), - null - ); - - this.add_main_option( - 'ring', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Ring'), - null - ); - - /* - * Sharing - */ - this.add_main_option( - 'share-file', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.FILENAME_ARRAY, - _('Share File'), - '<filepath|URI>' - ); - - this.add_main_option( - 'share-link', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING_ARRAY, - _('Share Link'), - '<URL>' - ); - - this.add_main_option( - 'share-text', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.STRING, - _('Share Text'), - '<text>' - ); - - /* - * Misc - */ - this.add_main_option( - 'version', - 'v'.charCodeAt(0), - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Show release version'), - null - ); - } - - _cliAction(id, name, parameter = null) { - const parameters = []; - - if (parameter instanceof GLib.Variant) - parameters[0] = parameter; - - id = id.replace(/\W+/g, '_'); - - Gio.DBus.session.call_sync( - 'org.gnome.Shell.Extensions.GSConnect', - `/org/gnome/Shell/Extensions/GSConnect/Device/${id}`, - 'org.gtk.Actions', - 'Activate', - GLib.Variant.new('(sava{sv})', [name, parameters, {}]), - null, - Gio.DBusCallFlags.NONE, - -1, - null - ); - } - - _cliListDevices(full = true) { - const result = Gio.DBus.session.call_sync( - 'org.gnome.Shell.Extensions.GSConnect', - '/org/gnome/Shell/Extensions/GSConnect', - 'org.freedesktop.DBus.ObjectManager', - 'GetManagedObjects', - null, - null, - Gio.DBusCallFlags.NONE, - -1, - null - ); - - const variant = result.unpack()[0].unpack(); - let device; - - for (let object of Object.values(variant)) { - object = object.recursiveUnpack(); - device = object['org.gnome.Shell.Extensions.GSConnect.Device']; - - if (full) - print(`${device.Id}\t${device.Name}\t${device.Connected}\t${device.Paired}`); - else if (device.Connected && device.Paired) - print(device.Id); - } - } - - _cliMessage(id, options) { - if (!options.contains('message-body')) - throw new TypeError('missing --message-body option'); - - // TODO: currently we only support single-recipient messaging - const addresses = options.lookup_value('message', null).deepUnpack(); - const body = options.lookup_value('message-body', null).deepUnpack(); - - this._cliAction( - id, - 'sendSms', - GLib.Variant.new('(ss)', [addresses[0], body]) - ); - } - - _cliNotify(id, options) { - const title = options.lookup_value('notification', null).unpack(); - let body = ''; - let icon = null; - let nid = `${Date.now()}`; - let appName = 'GSConnect CLI'; - - if (options.contains('notification-id')) - nid = options.lookup_value('notification-id', null).unpack(); - - if (options.contains('notification-body')) - body = options.lookup_value('notification-body', null).unpack(); - - if (options.contains('notification-appname')) - appName = options.lookup_value('notification-appname', null).unpack(); - - if (options.contains('notification-icon')) { - icon = options.lookup_value('notification-icon', null).unpack(); - icon = Gio.Icon.new_for_string(icon); - } else { - icon = new Gio.ThemedIcon({ - name: 'org.gnome.Shell.Extensions.GSConnect', - }); - } - - const notification = new GLib.Variant('a{sv}', { - appName: GLib.Variant.new_string(appName), - id: GLib.Variant.new_string(nid), - title: GLib.Variant.new_string(title), - text: GLib.Variant.new_string(body), - ticker: GLib.Variant.new_string(`${title}: ${body}`), - time: GLib.Variant.new_string(`${Date.now()}`), - isClearable: GLib.Variant.new_boolean(true), - icon: icon.serialize(), - }); - - this._cliAction(id, 'sendNotification', notification); - } - - _cliShareFile(device, options) { - const files = options.lookup_value('share-file', null).deepUnpack(); - - for (let file of files) { - file = new TextDecoder().decode(file); - this._cliAction(device, 'shareFile', GLib.Variant.new('(sb)', [file, false])); - } - } - - _cliShareLink(device, options) { - const uris = options.lookup_value('share-link', null).unpack(); - - for (const uri of uris) - this._cliAction(device, 'shareUri', uri); - } - - _cliShareText(device, options) { - const text = options.lookup_value('share-text', null).unpack(); - - this._cliAction(device, 'shareText', GLib.Variant.new_string(text)); - } - - vfunc_handle_local_options(options) { - try { - if (options.contains('version')) { - print(`GSConnect ${Config.PACKAGE_VERSION}`); - return 0; - } - - this.register(null); - - if (options.contains('list-devices')) { - this._cliListDevices(false); - return 0; - } - - if (options.contains('list-all')) { - this._cliListDevices(true); - return 0; - } - - // We need a device for anything else; exit since this is probably - // the daemon being started. - if (!options.contains('device')) - return -1; - - const id = options.lookup_value('device', null).unpack(); - - // Pairing - if (options.contains('pair')) { - this._cliAction(id, 'pair'); - return 0; - } - - if (options.contains('unpair')) { - this._cliAction(id, 'unpair'); - return 0; - } - - // Plugins - if (options.contains('message')) - this._cliMessage(id, options); - - if (options.contains('notification')) - this._cliNotify(id, options); - - if (options.contains('ping')) - this._cliAction(id, 'ping', GLib.Variant.new_string('')); - - if (options.contains('ring')) - this._cliAction(id, 'ring'); - - if (options.contains('share-file')) - this._cliShareFile(id, options); - - if (options.contains('share-link')) - this._cliShareLink(id, options); - - if (options.contains('share-text')) - this._cliShareText(id, options); - - return 0; - } catch (e) { - logError(e); - return 1; - } - } -}); - -await (new Service()).runAsync([system.programInvocationName].concat(ARGV)); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/device.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/device.js deleted file mode 100755 index aef96a2e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/device.js +++ /dev/null @@ -1,1105 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../config.js'; -import * as Components from './components/index.js'; -import * as Core from './core.js'; -import plugins from './plugins/index.js'; - -/** - * An object representing a remote device. - * - * Device class is subclassed from Gio.SimpleActionGroup so it implements the - * GActionGroup and GActionMap interfaces, like Gio.Application. - * - */ -const Device = GObject.registerClass({ - GTypeName: 'GSConnectDevice', - Properties: { - 'connected': GObject.ParamSpec.boolean( - 'connected', - 'Connected', - 'Whether the device is connected', - GObject.ParamFlags.READABLE, - false - ), - 'contacts': GObject.ParamSpec.object( - 'contacts', - 'Contacts', - 'The contacts store for this device', - GObject.ParamFlags.READABLE, - GObject.Object - ), - 'encryption-info': GObject.ParamSpec.string( - 'encryption-info', - 'Encryption Info', - 'A formatted string with the local and remote fingerprints', - GObject.ParamFlags.READABLE, - null - ), - 'icon-name': GObject.ParamSpec.string( - 'icon-name', - 'Icon Name', - 'Icon name representing the device', - GObject.ParamFlags.READABLE, - null - ), - 'id': GObject.ParamSpec.string( - 'id', - 'Id', - 'The device hostname or other network unique id', - GObject.ParamFlags.READABLE, - '' - ), - 'name': GObject.ParamSpec.string( - 'name', - 'Name', - 'The device name', - GObject.ParamFlags.READABLE, - null - ), - 'paired': GObject.ParamSpec.boolean( - 'paired', - 'Paired', - 'Whether the device is paired', - GObject.ParamFlags.READABLE, - false - ), - 'type': GObject.ParamSpec.string( - 'type', - 'Type', - 'The device type', - GObject.ParamFlags.READABLE, - null - ), - }, -}, class Device extends Gio.SimpleActionGroup { - - _init(identity) { - super._init(); - - this._id = identity.body.deviceId; - - // GLib.Source timeout id's for pairing requests - this._incomingPairRequest = 0; - this._outgoingPairRequest = 0; - - // Maps of name->Plugin, packet->Plugin, uuid->Transfer - this._plugins = new Map(); - this._handlers = new Map(); - this._procs = new Set(); - this._transfers = new Map(); - - this._outputLock = false; - this._outputQueue = []; - - // GSettings - this.settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect.Device', - true - ), - path: `/org/gnome/shell/extensions/gsconnect/device/${this.id}/`, - }); - this._migratePlugins(); - - // Watch for changes to supported and disabled plugins - this._disabledPluginsChangedId = this.settings.connect( - 'changed::disabled-plugins', - this._onAllowedPluginsChanged.bind(this) - ); - this._supportedPluginsChangedId = this.settings.connect( - 'changed::supported-plugins', - this._onAllowedPluginsChanged.bind(this) - ); - - this._registerActions(); - this.menu = new Gio.Menu(); - - // Parse identity if initialized with a proper packet, otherwise load - if (identity.id !== undefined) - this._handleIdentity(identity); - else - this._loadPlugins(); - } - - get channel() { - if (this._channel === undefined) - this._channel = null; - - return this._channel; - } - - get connected() { - if (this._connected === undefined) - this._connected = false; - - return this._connected; - } - - get connection_type() { - const lastConnection = this.settings.get_string('last-connection'); - - return lastConnection.split('://')[0]; - } - - get contacts() { - const contacts = this._plugins.get('contacts'); - - if (contacts && contacts.settings.get_boolean('contacts-source')) - return contacts._store; - - if (this._contacts === undefined) - this._contacts = Components.acquire('contacts'); - - return this._contacts; - } - - // FIXME: backend should do this stuff - get encryption_info() { - let localCert = null; - let remoteCert = null; - - // Bluetooth connections have no certificate so we use the host address - if (this.connection_type === 'bluetooth') { - // TRANSLATORS: Bluetooth address for remote device - return _('Bluetooth device at %s').format('???'); - - // If the device is connected use the certificate from the connection - } else if (this.connected) { - remoteCert = this.channel.peer_certificate; - - // Otherwise pull it out of the settings - } else if (this.paired) { - remoteCert = Gio.TlsCertificate.new_from_pem( - this.settings.get_string('certificate-pem'), - -1 - ); - } - - // FIXME: another ugly reach-around - let lanBackend; - - if (this.service !== null) - lanBackend = this.service.manager.backends.get('lan'); - - if (lanBackend && lanBackend.certificate) - localCert = lanBackend.certificate; - - - let verificationKey = ''; - if (localCert && remoteCert) { - let a = localCert.pubkey_der(); - let b = remoteCert.pubkey_der(); - if (a.compare(b) < 0) - [a, b] = [b, a]; // swap - const checksum = new GLib.Checksum(GLib.ChecksumType.SHA256); - checksum.update(a.toArray()); - checksum.update(b.toArray()); - verificationKey = checksum.get_string(); - } - - // TRANSLATORS: Label for TLS connection verification key - // - // Example: - // - // Verification key: 0123456789abcdef000000000000000000000000 - return _('Verification key: %s').format(verificationKey); - } - - get id() { - return this._id; - } - - get name() { - return this.settings.get_string('name'); - } - - get paired() { - return this.settings.get_boolean('paired'); - } - - get icon_name() { - switch (this.type) { - case 'laptop': - return 'laptop-symbolic'; - case 'phone': - return 'smartphone-symbolic'; - case 'tablet': - return 'tablet-symbolic'; - case 'tv': - return 'tv-symbolic'; - case 'desktop': - default: - return 'computer-symbolic'; - } - } - - get service() { - if (this._service === undefined) - this._service = Gio.Application.get_default(); - - return this._service; - } - - get type() { - return this.settings.get_string('type'); - } - - _migratePlugins() { - const deprecated = ['photo']; - const supported = this.settings - .get_strv('supported-plugins') - .filter(name => !deprecated.includes(name)); - - this.settings.set_strv('supported-plugins', supported); - } - - _handleIdentity(packet) { - this.freeze_notify(); - - // If we're connected, record the reconnect URI - if (this.channel !== null) - this.settings.set_string('last-connection', this.channel.address); - - // The type won't change, but it might not be properly set yet - if (this.type !== packet.body.deviceType) { - this.settings.set_string('type', packet.body.deviceType); - this.notify('type'); - this.notify('icon-name'); - } - - // The name may change so we check and notify if so - if (this.name !== packet.body.deviceName) { - this.settings.set_string('name', packet.body.deviceName); - this.notify('name'); - } - - // Packets - const incoming = packet.body.incomingCapabilities.sort(); - const outgoing = packet.body.outgoingCapabilities.sort(); - const inc = this.settings.get_strv('incoming-capabilities'); - const out = this.settings.get_strv('outgoing-capabilities'); - - // Only write GSettings if something has changed - if (incoming.join('') !== inc.join('') || outgoing.join('') !== out.join('')) { - this.settings.set_strv('incoming-capabilities', incoming); - this.settings.set_strv('outgoing-capabilities', outgoing); - } - - // Determine supported plugins by matching incoming to outgoing types - const supported = []; - - for (const name in plugins) { - const meta = plugins[name].Metadata; - - if (meta === undefined) - continue; - - // If we can handle packets it sends or send packets it can handle - if (meta.incomingCapabilities.some(t => outgoing.includes(t)) || - meta.outgoingCapabilities.some(t => incoming.includes(t))) - supported.push(name); - } - - // Only write GSettings if something has changed - const currentSupported = this.settings.get_strv('supported-plugins'); - - if (currentSupported.join('') !== supported.sort().join('')) - this.settings.set_strv('supported-plugins', supported); - - this.thaw_notify(); - } - - /** - * Set the channel and start sending/receiving packets. If %null is passed - * the device becomes disconnected. - * - * @param {Core.Channel} [channel] - The new channel - */ - setChannel(channel = null) { - if (this.channel === channel) - return; - - if (this.channel !== null) - this.channel.close(); - - this._channel = channel; - - // If we've disconnected empty the queue, otherwise restart the read - // loop and update the device metadata - if (this.channel === null) { - this._outputQueue.length = 0; - } else { - this._handleIdentity(this.channel.identity); - this._readLoop(channel); - } - - // The connected state didn't change - if (this.connected === !!this.channel) - return; - - // Notify and trigger plugins - this._connected = !!this.channel; - this.notify('connected'); - this._triggerPlugins(); - } - - async _readLoop(channel) { - try { - let packet = null; - - while ((packet = await this.channel.readPacket())) { - debug(packet, this.name); - this.handlePacket(packet); - } - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - debug(e, this.name); - - if (this.channel === channel) - this.setChannel(null); - } - } - - _processExit(proc, result) { - try { - proc.wait_check_finish(result); - } catch (e) { - debug(e); - } - - this.delete(proc); - } - - /** - * Launch a subprocess for the device. If the device becomes unpaired, it is - * assumed the device is no longer trusted and all subprocesses will be - * killed. - * - * @param {string[]} args - process arguments - * @param {Gio.Cancellable} [cancellable] - optional cancellable - * @return {Gio.Subprocess} The subprocess - */ - launchProcess(args, cancellable = null) { - if (this._launcher === undefined) { - const application = GLib.build_filenamev([ - Config.PACKAGE_DATADIR, - 'service', - 'daemon.js', - ]); - - this._launcher = new Gio.SubprocessLauncher(); - this._launcher.setenv('GSCONNECT', application, false); - this._launcher.setenv('GSCONNECT_DEVICE_ID', this.id, false); - this._launcher.setenv('GSCONNECT_DEVICE_NAME', this.name, false); - this._launcher.setenv('GSCONNECT_DEVICE_ICON', this.icon_name, false); - this._launcher.setenv( - 'GSCONNECT_DEVICE_DBUS', - `${Config.APP_PATH}/Device/${this.id.replace(/\W+/g, '_')}`, - false - ); - } - - // Create and track the process - const proc = this._launcher.spawnv(args); - proc.wait_check_async(cancellable, this._processExit.bind(this._procs)); - this._procs.add(proc); - - return proc; - } - - /** - * Handle a packet and pass it to the appropriate plugin. - * - * @param {Core.Packet} packet - The incoming packet object - * @return {undefined} no return value - */ - handlePacket(packet) { - try { - if (packet.type === 'kdeconnect.pair') - return this._handlePair(packet); - - // The device must think we're paired; inform it we are not - if (!this.paired) - return this.unpair(); - - const handler = this._handlers.get(packet.type); - - if (handler !== undefined) - handler.handlePacket(packet); - else - debug(`Unsupported packet type (${packet.type})`, this.name); - } catch (e) { - debug(e, this.name); - } - } - - /** - * Send a packet to the device. - * - * @param {Object} packet - An object of packet data... - */ - async sendPacket(packet) { - try { - if (!this.connected) - return; - - if (!this.paired && packet.type !== 'kdeconnect.pair') - return; - - this._outputQueue.push(new Core.Packet(packet)); - - if (this._outputLock) - return; - - this._outputLock = true; - let next; - - while ((next = this._outputQueue.shift())) { - await this.channel.sendPacket(next); - debug(next, this.name); - } - - this._outputLock = false; - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - debug(e, this.name); - - this._outputLock = false; - } - } - - /** - * Actions - */ - _registerActions() { - // Pairing notification actions - const acceptPair = new Gio.SimpleAction({name: 'pair'}); - acceptPair.connect('activate', this.pair.bind(this)); - this.add_action(acceptPair); - - const rejectPair = new Gio.SimpleAction({name: 'unpair'}); - rejectPair.connect('activate', this.unpair.bind(this)); - this.add_action(rejectPair); - - // Transfer notification actions - const cancelTransfer = new Gio.SimpleAction({ - name: 'cancelTransfer', - parameter_type: new GLib.VariantType('s'), - }); - cancelTransfer.connect('activate', this.cancelTransfer.bind(this)); - this.add_action(cancelTransfer); - - const openPath = new Gio.SimpleAction({ - name: 'openPath', - parameter_type: new GLib.VariantType('s'), - }); - openPath.connect('activate', this.openPath); - this.add_action(openPath); - - const showPathInFolder = new Gio.SimpleAction({ - name: 'showPathInFolder', - parameter_type: new GLib.VariantType('s'), - }); - showPathInFolder.connect('activate', this.showPathInFolder); - this.add_action(showPathInFolder); - - // Preference helpers - const clearCache = new Gio.SimpleAction({ - name: 'clearCache', - parameter_type: null, - }); - clearCache.connect('activate', this._clearCache.bind(this)); - this.add_action(clearCache); - } - - /** - * Get the position of a GMenuItem with @actionName in the top level of the - * device menu. - * - * @param {string} actionName - An action name with scope (eg. device.foo) - * @return {number} An 0-based index or -1 if not found - */ - getMenuAction(actionName) { - for (let i = 0, len = this.menu.get_n_items(); i < len; i++) { - try { - const val = this.menu.get_item_attribute_value(i, 'action', null); - - if (val.unpack() === actionName) - return i; - } catch (e) { - continue; - } - } - - return -1; - } - - /** - * Add a GMenuItem to the top level of the device menu - * - * @param {Gio.MenuItem} menuItem - A GMenuItem - * @param {number} [index] - The position to place the item - * @return {number} The position the item was placed - */ - addMenuItem(menuItem, index = -1) { - try { - if (index > -1) { - this.menu.insert_item(index, menuItem); - return index; - } - - this.menu.append_item(menuItem); - return this.menu.get_n_items(); - } catch (e) { - debug(e, this.name); - return -1; - } - } - - /** - * Add a Device GAction to the top level of the device menu - * - * @param {Gio.Action} action - A GAction - * @param {number} [index] - The position to place the item - * @param {string} label - A label for the item - * @param {string} icon_name - A themed icon name for the item - * @return {number} The position the item was placed - */ - addMenuAction(action, index = -1, label, icon_name) { - try { - const item = new Gio.MenuItem(); - - if (label) - item.set_label(label); - - if (icon_name) - item.set_icon(new Gio.ThemedIcon({name: icon_name})); - - item.set_attribute_value( - 'hidden-when', - new GLib.Variant('s', 'action-disabled') - ); - - item.set_detailed_action(`device.${action.name}`); - - return this.addMenuItem(item, index); - } catch (e) { - debug(e, this.name); - return -1; - } - } - - /** - * Remove a GAction from the top level of the device menu by action name - * - * @param {string} actionName - A GAction name, including scope - * @return {number} The position the item was removed from or -1 - */ - removeMenuAction(actionName) { - try { - const index = this.getMenuAction(actionName); - - if (index > -1) - this.menu.remove(index); - - return index; - } catch (e) { - debug(e, this.name); - return -1; - } - } - - /** - * Withdraw a device notification. - * - * @param {string} id - Id for the notification to withdraw - */ - hideNotification(id) { - if (this.service === null) - return; - - this.service.withdraw_notification(`${this.id}|${id}`); - } - - /** - * Show a device notification. - * - * @param {Object} params - A dictionary of notification parameters - * @param {number} [params.id] - A UNIX epoch timestamp (ms) - * @param {string} [params.title] - A title - * @param {string} [params.body] - A body - * @param {Gio.Icon} [params.icon] - An icon - * @param {Gio.NotificationPriority} [params.priority] - The priority - * @param {Array} [params.actions] - A dictionary of action parameters - * @param {Array} [params.buttons] - An Array of buttons - */ - showNotification(params) { - if (this.service === null) - return; - - // KDE Connect on Android can sometimes give an undefined for params.body - Object.keys(params) - .forEach(key => params[key] === undefined && delete params[key]); - - params = Object.assign({ - id: Date.now(), - title: this.name, - body: '', - icon: new Gio.ThemedIcon({name: this.icon_name}), - priority: Gio.NotificationPriority.NORMAL, - action: null, - buttons: [], - }, params); - - const notif = new Gio.Notification(); - notif.set_title(params.title); - notif.set_body(params.body); - notif.set_icon(params.icon); - notif.set_priority(params.priority); - - // Default Action - if (params.action) { - const hasParameter = (params.action.parameter !== null); - - if (!hasParameter) - params.action.parameter = new GLib.Variant('s', ''); - - notif.set_default_action_and_target( - 'app.device', - new GLib.Variant('(ssbv)', [ - this.id, - params.action.name, - hasParameter, - params.action.parameter, - ]) - ); - } - - // Buttons - for (const button of params.buttons) { - const hasParameter = (button.parameter !== null); - - if (!hasParameter) - button.parameter = new GLib.Variant('s', ''); - - notif.add_button_with_target( - button.label, - 'app.device', - new GLib.Variant('(ssbv)', [ - this.id, - button.action, - hasParameter, - button.parameter, - ]) - ); - } - - this.service.send_notification(`${this.id}|${params.id}`, notif); - } - - /** - * Cancel an ongoing file transfer. - * - * @param {Gio.Action} action - The GAction - * @param {GLib.Variant} parameter - The activation parameter - */ - cancelTransfer(action, parameter) { - try { - const uuid = parameter.unpack(); - const transfer = this._transfers.get(uuid); - - if (transfer === undefined) - return; - - this._transfers.delete(uuid); - transfer.cancel(); - } catch (e) { - logError(e, this.name); - } - } - - /** - * Create a transfer object. - * - * @return {Core.Transfer} A new transfer - */ - createTransfer() { - const transfer = new Core.Transfer({device: this}); - - // Track the transfer - this._transfers.set(transfer.uuid, transfer); - - transfer.connect('notify::completed', (transfer) => { - this._transfers.delete(transfer.uuid); - }); - - return transfer; - } - - /** - * Reject the transfer payload described by @packet. - * - * @param {Core.Packet} packet - A packet - * @return {Promise} A promise for the operation - */ - rejectTransfer(packet) { - if (!packet || !packet.hasPayload()) - return; - - return this.channel.rejectTransfer(packet); - } - - openPath(action, parameter) { - const path = parameter.unpack(); - - // Normalize paths to URIs, assuming local file - const uri = path.includes('://') ? path : `file://${path}`; - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } - - showPathInFolder(action, parameter) { - const path = parameter.unpack(); - const uri = path.includes('://') ? path : `file://${path}`; - - const connection = Gio.DBus.session; - connection.call( - 'org.freedesktop.FileManager1', - '/org/freedesktop/FileManager1', - 'org.freedesktop.FileManager1', - 'ShowItems', - new GLib.Variant('(ass)', [[uri], 's']), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (connection, res) => { - try { - connection.call_finish(res); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - logError(e); - } - } - ); - } - - _clearCache(action, parameter) { - for (const plugin of this._plugins.values()) { - try { - plugin.clearCache(); - } catch (e) { - debug(e, this.name); - } - } - } - - /** - * Pair request handler - * - * @param {Core.Packet} packet - A complete kdeconnect.pair packet - */ - _handlePair(packet) { - // A pair has been requested/confirmed - if (packet.body.pair) { - // The device is accepting our request - if (this._outgoingPairRequest) { - this._setPaired(true); - this._loadPlugins(); - - // The device thinks we're unpaired - } else if (this.paired) { - this._setPaired(true); - this.sendPacket({ - type: 'kdeconnect.pair', - body: {pair: true}, - }); - this._triggerPlugins(); - - // The device is requesting pairing - } else { - this._notifyPairRequest(); - } - // Device is requesting unpairing/rejecting our request - } else { - this._setPaired(false); - this._unloadPlugins(); - } - } - - /** - * Notify the user of an incoming pair request and set a 30s timeout - */ - _notifyPairRequest() { - // Reset any active request - this._resetPairRequest(); - - this.showNotification({ - id: 'pair-request', - // TRANSLATORS: eg. Pair Request from Google Pixel - title: _('Pair Request from %s').format(this.name), - body: this.encryption_info, - icon: new Gio.ThemedIcon({name: 'channel-insecure-symbolic'}), - priority: Gio.NotificationPriority.URGENT, - buttons: [ - { - action: 'unpair', - label: _('Reject'), - parameter: null, - }, - { - action: 'pair', - label: _('Accept'), - parameter: null, - }, - ], - }); - - // Start a 30s countdown - this._incomingPairRequest = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, - 30, - this._setPaired.bind(this, false) - ); - } - - /** - * Reset pair request timeouts and withdraw any notifications - */ - _resetPairRequest() { - this.hideNotification('pair-request'); - - if (this._incomingPairRequest) { - GLib.source_remove(this._incomingPairRequest); - this._incomingPairRequest = 0; - } - - if (this._outgoingPairRequest) { - GLib.source_remove(this._outgoingPairRequest); - this._outgoingPairRequest = 0; - } - } - - /** - * Set the internal paired state of the device and emit ::notify - * - * @param {boolean} paired - The paired state to set - */ - _setPaired(paired) { - this._resetPairRequest(); - - // For TCP connections we store or reset the TLS Certificate - if (this.connection_type === 'lan') { - if (paired) { - this.settings.set_string( - 'certificate-pem', - this.channel.peer_certificate.certificate_pem - ); - } else { - this.settings.reset('certificate-pem'); - } - } - - // If we've become unpaired, stop all subprocesses and transfers - if (!paired) { - for (const proc of this._procs) - proc.force_exit(); - - this._procs.clear(); - - for (const transfer of this._transfers.values()) - transfer.close(); - - this._transfers.clear(); - } - - this.settings.set_boolean('paired', paired); - this.notify('paired'); - } - - /** - * Send or accept an incoming pair request; also exported as a GAction - */ - pair() { - try { - // If we're accepting an incoming pair request, set the internal - // paired state and send the confirmation before loading plugins. - if (this._incomingPairRequest) { - this._setPaired(true); - - this.sendPacket({ - type: 'kdeconnect.pair', - body: {pair: true}, - }); - - this._loadPlugins(); - - // If we're initiating an outgoing pair request, be sure the timer - // is reset before sending the request and setting a 30s timeout. - } else if (!this.paired) { - this._resetPairRequest(); - - this.sendPacket({ - type: 'kdeconnect.pair', - body: {pair: true}, - }); - - this._outgoingPairRequest = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, - 30, - this._setPaired.bind(this, false) - ); - } - } catch (e) { - logError(e, this.name); - } - } - - /** - * Unpair or reject an incoming pair request; also exported as a GAction - */ - unpair() { - try { - if (this.connected) { - this.sendPacket({ - type: 'kdeconnect.pair', - body: {pair: false}, - }); - } - - this._setPaired(false); - this._unloadPlugins(); - } catch (e) { - logError(e, this.name); - } - } - - /* - * Plugin Functions - */ - _onAllowedPluginsChanged(settings) { - const disabled = this.settings.get_strv('disabled-plugins'); - const supported = this.settings.get_strv('supported-plugins'); - const allowed = supported.filter(name => !disabled.includes(name)); - - // Unload any plugins that are disabled or unsupported - this._plugins.forEach(plugin => { - if (!allowed.includes(plugin.name)) - this._unloadPlugin(plugin.name); - }); - - // Make sure we change the contacts store if the plugin was disabled - if (!allowed.includes('contacts')) - this.notify('contacts'); - - // Load allowed plugins - for (const name of allowed) - this._loadPlugin(name); - } - - _loadPlugin(name) { - let handler, plugin; - - try { - if (this.paired && !this._plugins.has(name)) { - // Instantiate the handler - handler = plugins[name]; - plugin = new handler.default(this); - - // Register packet handlers - for (const packetType of handler.Metadata.incomingCapabilities) - this._handlers.set(packetType, plugin); - - // Register plugin - this._plugins.set(name, plugin); - - // Run the connected()/disconnected() handler - if (this.connected) - plugin.connected(); - else - plugin.disconnected(); - } - } catch (e) { - if (plugin !== undefined) - plugin.destroy(); - - if (this.service !== null) - this.service.notify_error(e); - else - logError(e, this.name); - } - } - - async _loadPlugins() { - const disabled = this.settings.get_strv('disabled-plugins'); - - for (const name of this.settings.get_strv('supported-plugins')) { - if (!disabled.includes(name)) - await this._loadPlugin(name); - } - } - - _unloadPlugin(name) { - let handler, plugin; - - try { - if (this._plugins.has(name)) { - // Unregister packet handlers - handler = plugins[name]; - - for (const type of handler.Metadata.incomingCapabilities) - this._handlers.delete(type); - - // Unregister plugin - plugin = this._plugins.get(name); - this._plugins.delete(name); - plugin.destroy(); - } - } catch (e) { - logError(e, this.name); - } - } - - async _unloadPlugins() { - for (const name of this._plugins.keys()) - await this._unloadPlugin(name); - } - - _triggerPlugins() { - for (const plugin of this._plugins.values()) { - if (this.connected) - plugin.connected(); - else - plugin.disconnected(); - } - } - - destroy() { - // Drop the default contacts store if we were using it - if (this._contacts !== undefined) - this._contacts = Components.release('contacts'); - - // Close the channel if still connected - if (this.channel !== null) - this.channel.close(); - - // Synchronously destroy plugins - this._plugins.forEach(plugin => plugin.destroy()); - this._plugins.clear(); - - // Dispose GSettings - this.settings.disconnect(this._disabledPluginsChangedId); - this.settings.disconnect(this._supportedPluginsChangedId); - this.settings.run_dispose(); - - GObject.signal_handlers_destroy(this); - } -}); - -export default Device; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/init.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/init.js deleted file mode 100755 index 313c70bd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/init.js +++ /dev/null @@ -1,428 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import {watchService} from '../wl_clipboard.js'; - -import Gio from 'gi://Gio'; -import GIRepository from 'gi://GIRepository'; -import GLib from 'gi://GLib'; - -import Config from '../config.js'; -import setup, {setupGettext} from '../utils/setup.js'; - - -// Promise Wrappers -// We don't use top-level await since it returns control flow to importing module, causing bugs -import('gi://EBook').then(({default: EBook}) => { - Gio._promisify(EBook.BookClient, 'connect'); - Gio._promisify(EBook.BookClient.prototype, 'get_view'); - Gio._promisify(EBook.BookClient.prototype, 'get_contacts'); -}).catch(console.debug); -import('gi://EDataServer').then(({default: EDataServer}) => { - Gio._promisify(EDataServer.SourceRegistry, 'new'); -}).catch(console.debug); - -Gio._promisify(Gio.AsyncInitable.prototype, 'init_async'); -Gio._promisify(Gio.DBusConnection.prototype, 'call'); -Gio._promisify(Gio.DBusProxy.prototype, 'call'); -Gio._promisify(Gio.DataInputStream.prototype, 'read_line_async', - 'read_line_finish_utf8'); -Gio._promisify(Gio.File.prototype, 'delete_async'); -Gio._promisify(Gio.File.prototype, 'enumerate_children_async'); -Gio._promisify(Gio.File.prototype, 'load_contents_async'); -Gio._promisify(Gio.File.prototype, 'mount_enclosing_volume'); -Gio._promisify(Gio.File.prototype, 'query_info_async'); -Gio._promisify(Gio.File.prototype, 'read_async'); -Gio._promisify(Gio.File.prototype, 'replace_async'); -Gio._promisify(Gio.File.prototype, 'replace_contents_bytes_async', - 'replace_contents_finish'); -Gio._promisify(Gio.FileEnumerator.prototype, 'next_files_async'); -Gio._promisify(Gio.Mount.prototype, 'unmount_with_operation'); -Gio._promisify(Gio.InputStream.prototype, 'close_async'); -Gio._promisify(Gio.OutputStream.prototype, 'close_async'); -Gio._promisify(Gio.OutputStream.prototype, 'splice_async'); -Gio._promisify(Gio.OutputStream.prototype, 'write_all_async'); -Gio._promisify(Gio.SocketClient.prototype, 'connect_async'); -Gio._promisify(Gio.SocketListener.prototype, 'accept_async'); -Gio._promisify(Gio.Subprocess.prototype, 'communicate_utf8_async'); -Gio._promisify(Gio.Subprocess.prototype, 'wait_check_async'); -Gio._promisify(Gio.TlsConnection.prototype, 'handshake_async'); -Gio._promisify(Gio.DtlsConnection.prototype, 'handshake_async'); - - -// User Directories -Config.CACHEDIR = GLib.build_filenamev([GLib.get_user_cache_dir(), 'gsconnect']); -Config.CONFIGDIR = GLib.build_filenamev([GLib.get_user_config_dir(), 'gsconnect']); -Config.RUNTIMEDIR = GLib.build_filenamev([GLib.get_user_runtime_dir(), 'gsconnect']); - -// Bootstrap -const serviceFolder = GLib.path_get_dirname(GLib.filename_from_uri(import.meta.url)[0]); -const extensionFolder = GLib.path_get_dirname(serviceFolder); -setup(extensionFolder); -setupGettext(); - -if (Config.IS_USER) { - // Infer libdir by assuming gnome-shell shares a common prefix with gjs; - // assume the parent directory if it's not there - let libdir = GIRepository.Repository.get_search_path().find(path => { - return path.endsWith('/gjs/girepository-1.0'); - }).replace('/gjs/girepository-1.0', ''); - - const gsdir = GLib.build_filenamev([libdir, 'gnome-shell']); - - if (!GLib.file_test(gsdir, GLib.FileTest.IS_DIR)) { - const currentDir = `/${GLib.path_get_basename(libdir)}`; - libdir = libdir.replace(currentDir, ''); - } - - Config.GNOME_SHELL_LIBDIR = libdir; -} - - -// Load DBus interfaces -Config.DBUS = (() => { - const bytes = Gio.resources_lookup_data( - GLib.build_filenamev([Config.APP_PATH, `${Config.APP_ID}.xml`]), - Gio.ResourceLookupFlags.NONE - ); - - const xml = new TextDecoder().decode(bytes.toArray()); - const dbus = Gio.DBusNodeInfo.new_for_xml(xml); - dbus.nodes.forEach(info => info.cache_build()); - - return dbus; -})(); - - -// Init User Directories -for (const path of [Config.CACHEDIR, Config.CONFIGDIR, Config.RUNTIMEDIR]) - GLib.mkdir_with_parents(path, 0o755); - - -globalThis.HAVE_GNOME = GLib.getenv('GSCONNECT_MODE')?.toLowerCase() !== 'cli' && (GLib.getenv('GNOME_SETUP_DISPLAY') !== null || GLib.getenv('XDG_CURRENT_DESKTOP')?.toUpperCase()?.includes('GNOME') || GLib.getenv('XDG_SESSION_DESKTOP')?.toLowerCase() === 'gnome'); - - -/** - * A custom debug function that logs at LEVEL_MESSAGE to avoid the need for env - * variables to be set. - * - * @param {Error|string} message - A string or Error to log - * @param {string} [prefix] - An optional prefix for the warning - */ -const _debugCallerMatch = new RegExp(/([^@]*)@([^:]*):([^:]*)/); -// eslint-disable-next-line func-style -const _debugFunc = function (error, prefix = null) { - let caller, message; - - if (error.stack) { - caller = error.stack.split('\n')[0]; - message = `${error.message}\n${error.stack}`; - } else { - caller = (new Error()).stack.split('\n')[1]; - message = JSON.stringify(error, null, 2); - } - - if (prefix) - message = `${prefix}: ${message}`; - - const [, func, file, line] = _debugCallerMatch.exec(caller); - const script = file.replace(Config.PACKAGE_DATADIR, ''); - - GLib.log_structured('GSConnect', GLib.LogLevelFlags.LEVEL_MESSAGE, { - 'MESSAGE': `[${script}:${func}:${line}]: ${message}`, - 'SYSLOG_IDENTIFIER': 'org.gnome.Shell.Extensions.GSConnect', - 'CODE_FILE': file, - 'CODE_FUNC': func, - 'CODE_LINE': line, - }); -}; - -// Swap the function out for a no-op anonymous function for speed -const settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true), -}); - -settings.connect('changed::debug', (settings, key) => { - globalThis.debug = settings.get_boolean(key) ? _debugFunc : () => {}; -}); - -if (settings.get_boolean('debug')) - globalThis.debug = _debugFunc; -else - globalThis.debug = () => {}; - - -/** - * Start wl_clipboard if not under Gnome - */ -if (!globalThis.HAVE_GNOME) { - debug('Not running as a Gnome extension'); - watchService(); -} - - -/** - * A simple (for now) pre-comparison sanitizer for phone numbers - * See: https://github.com/KDE/kdeconnect-kde/blob/master/smsapp/conversationlistmodel.cpp#L200-L210 - * - * @return {string} Return the string stripped of leading 0, and ' ()-+' - */ -String.prototype.toPhoneNumber = function () { - const strippedNumber = this.replace(/^0*|[ ()+-]/g, ''); - - if (strippedNumber.length) - return strippedNumber; - - return this; -}; - - -/** - * A simple equality check for phone numbers based on `toPhoneNumber()` - * - * @param {string} number - A phone number string to compare - * @return {boolean} If `this` and @number are equivalent phone numbers - */ -String.prototype.equalsPhoneNumber = function (number) { - const a = this.toPhoneNumber(); - const b = number.toPhoneNumber(); - - return (a.length && b.length && (a.endsWith(b) || b.endsWith(a))); -}; - - -/** - * An implementation of `rm -rf` in Gio - * - * @param {Gio.File|string} file - a GFile or filepath - */ -Gio.File.rm_rf = function (file) { - try { - if (typeof file === 'string') - file = Gio.File.new_for_path(file); - - try { - const iter = file.enumerate_children( - 'standard::name', - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null - ); - - let info; - - while ((info = iter.next_file(null))) - Gio.File.rm_rf(iter.get_child(info)); - - iter.close(null); - } catch (e) { - // Silence errors - } - - file.delete(null); - } catch (e) { - // Silence errors - } -}; - - -/** - * Extend GLib.Variant with a static method to recursively pack a variant - * - * @param {*} [obj] - May be a GLib.Variant, Array, standard Object or literal. - * @return {GLib.Variant} The resulting GVariant - */ -function _full_pack(obj) { - let packed; - const type = typeof obj; - - switch (true) { - case (obj instanceof GLib.Variant): - return obj; - - case (type === 'string'): - return GLib.Variant.new('s', obj); - - case (type === 'number'): - return GLib.Variant.new('d', obj); - - case (type === 'boolean'): - return GLib.Variant.new('b', obj); - - case (obj instanceof Uint8Array): - return GLib.Variant.new('ay', obj); - - case (obj === null): - return GLib.Variant.new('mv', null); - - case (typeof obj.map === 'function'): - return GLib.Variant.new( - 'av', - obj.filter(e => e !== undefined).map(e => _full_pack(e)) - ); - - case (obj instanceof Gio.Icon): - return obj.serialize(); - - case (type === 'object'): - packed = {}; - - for (const [key, val] of Object.entries(obj)) { - if (val !== undefined) - packed[key] = _full_pack(val); - } - - return GLib.Variant.new('a{sv}', packed); - - default: - throw Error(`Unsupported type '${type}': ${obj}`); - } -} - -GLib.Variant.full_pack = _full_pack; - - -/** - * Extend GLib.Variant with a method to recursively deepUnpack() a variant - * - * @param {*} [obj] - May be a GLib.Variant, Array, standard Object or literal. - * @return {*} The resulting object - */ -function _full_unpack(obj) { - obj = (obj === undefined) ? this : obj; - const unpacked = {}; - - switch (true) { - case (obj === null): - return obj; - - case (obj instanceof GLib.Variant): - return _full_unpack(obj.deepUnpack()); - - case (obj instanceof Uint8Array): - return obj; - - case (typeof obj.map === 'function'): - return obj.map(e => _full_unpack(e)); - - case (typeof obj === 'object'): - for (const [key, value] of Object.entries(obj)) { - // Try to detect and deserialize GIcons - try { - if (key === 'icon' && value.get_type_string() === '(sv)') - unpacked[key] = Gio.Icon.deserialize(value); - else - unpacked[key] = _full_unpack(value); - } catch (e) { - unpacked[key] = _full_unpack(value); - } - } - - return unpacked; - - default: - return obj; - } -} - -GLib.Variant.prototype.full_unpack = _full_unpack; - - -/** - * Creates a GTlsCertificate from the PEM-encoded data in @cert_path and - * @key_path. If either are missing a new pair will be generated. - * - * Additionally, the private key will be added using ssh-add to allow sftp - * connections using Gio. - * - * See: https://github.com/KDE/kdeconnect-kde/blob/master/core/kdeconnectconfig.cpp#L119 - * - * @param {string} certPath - Absolute path to a x509 certificate in PEM format - * @param {string} keyPath - Absolute path to a private key in PEM format - * @param {string} commonName - A unique common name for the certificate - * @return {Gio.TlsCertificate} A TLS certificate - */ -Gio.TlsCertificate.new_for_paths = function (certPath, keyPath, commonName = null) { - // Check if the certificate/key pair already exists - const certExists = GLib.file_test(certPath, GLib.FileTest.EXISTS); - const keyExists = GLib.file_test(keyPath, GLib.FileTest.EXISTS); - - // Create a new certificate and private key if necessary - if (!certExists || !keyExists) { - // If we weren't passed a common name, generate a random one - if (!commonName) - commonName = GLib.uuid_string_random(); - - const proc = new Gio.Subprocess({ - argv: [ - Config.OPENSSL_PATH, 'req', - '-new', '-x509', '-sha256', - '-out', certPath, - '-newkey', 'rsa:4096', '-nodes', - '-keyout', keyPath, - '-days', '3650', - '-subj', `/O=andyholmes.github.io/OU=GSConnect/CN=${commonName}`, - ], - flags: (Gio.SubprocessFlags.STDOUT_SILENCE | - Gio.SubprocessFlags.STDERR_SILENCE), - }); - proc.init(null); - proc.wait_check(null); - } - - return Gio.TlsCertificate.new_from_files(certPath, keyPath); -}; - -Object.defineProperties(Gio.TlsCertificate.prototype, { - /** - * The common name of the certificate. - */ - 'common_name': { - get: function () { - if (!this.__common_name) { - const proc = new Gio.Subprocess({ - argv: [Config.OPENSSL_PATH, 'x509', '-noout', '-subject', '-inform', 'pem'], - flags: Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE, - }); - proc.init(null); - - const stdout = proc.communicate_utf8(this.certificate_pem, null)[1]; - this.__common_name = /(?:cn|CN) ?= ?([^,\n]*)/.exec(stdout)[1]; - } - - return this.__common_name; - }, - configurable: true, - enumerable: true, - }, - - /** - * Get just the pubkey as a DER ByteArray of a certificate. - * - * @return {GLib.Bytes} The pubkey as DER of the certificate. - */ - 'pubkey_der': { - value: function () { - if (!this.__pubkey_der) { - let proc = new Gio.Subprocess({ - argv: [Config.OPENSSL_PATH, 'x509', '-noout', '-pubkey', '-inform', 'pem'], - flags: Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE, - }); - proc.init(null); - - const pubkey = proc.communicate_utf8(this.certificate_pem, null)[1]; - proc = new Gio.Subprocess({ - argv: [Config.OPENSSL_PATH, 'pkey', '-pubin', '-inform', 'pem', '-outform', 'der'], - flags: Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDOUT_PIPE, - }); - proc.init(null); - this.__pubkey_der = proc.communicate(new TextEncoder().encode(pubkey), null)[1]; - } - - return this.__pubkey_der; - }, - configurable: true, - enumerable: false, - }, - -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/manager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/manager.js deleted file mode 100755 index 1f3f86d1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/manager.js +++ /dev/null @@ -1,515 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../config.js'; -import * as DBus from './utils/dbus.js'; -import Device from './device.js'; - -import * as LanBackend from './backends/lan.js'; - -const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device'; -const DEVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect/Device'; -const DEVICE_IFACE = Config.DBUS.lookup_interface(DEVICE_NAME); - - -const backends = { - lan: LanBackend, -}; - - -/** - * A manager for devices. - */ -const Manager = GObject.registerClass({ - GTypeName: 'GSConnectManager', - Properties: { - 'active': GObject.ParamSpec.boolean( - 'active', - 'Active', - 'Whether the manager is active', - GObject.ParamFlags.READABLE, - false - ), - 'discoverable': GObject.ParamSpec.boolean( - 'discoverable', - 'Discoverable', - 'Whether the service responds to discovery requests', - GObject.ParamFlags.READWRITE, - false - ), - 'id': GObject.ParamSpec.string( - 'id', - 'Id', - 'The hostname or other network unique id', - GObject.ParamFlags.READWRITE, - null - ), - 'name': GObject.ParamSpec.string( - 'name', - 'Name', - 'The name announced to the network', - GObject.ParamFlags.READWRITE, - 'GSConnect' - ), - }, -}, class Manager extends Gio.DBusObjectManagerServer { - - _init(params = {}) { - super._init(params); - - this._exported = new WeakMap(); - this._reconnectId = 0; - - this._settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true), - }); - this._initSettings(); - } - - get active() { - if (this._active === undefined) - this._active = false; - - return this._active; - } - - get backends() { - if (this._backends === undefined) - this._backends = new Map(); - - return this._backends; - } - - get devices() { - if (this._devices === undefined) - this._devices = new Map(); - - return this._devices; - } - - get discoverable() { - if (this._discoverable === undefined) - this._discoverable = this.settings.get_boolean('discoverable'); - - return this._discoverable; - } - - set discoverable(value) { - if (this.discoverable === value) - return; - - this._discoverable = value; - this.notify('discoverable'); - - // FIXME: This whole thing just keeps getting uglier - const application = Gio.Application.get_default(); - - if (application === null) - return; - - if (this.discoverable) { - Gio.Application.prototype.withdraw_notification.call( - application, - 'discovery-warning' - ); - } else { - const notif = new Gio.Notification(); - notif.set_title(_('Discovery Disabled')); - notif.set_body(_('Discovery has been disabled due to the number of devices on this network.')); - notif.set_icon(new Gio.ThemedIcon({name: 'dialog-warning'})); - notif.set_priority(Gio.NotificationPriority.HIGH); - notif.set_default_action('app.preferences'); - - Gio.Application.prototype.withdraw_notification.call( - application, - 'discovery-warning', - notif - ); - } - } - - get id() { - if (this._id === undefined) - this._id = this.settings.get_string('id'); - - return this._id; - } - - set id(value) { - if (this.id === value) - return; - - this._id = value; - this.notify('id'); - } - - get name() { - if (this._name === undefined) - this._name = this.settings.get_string('name'); - - return this._name; - } - - set name(value) { - if (this.name === value) - return; - - this._name = value; - this.notify('name'); - - // Broadcast changes to the network - for (const backend of this.backends.values()) { - backend.name = this.name; - backend.buildIdentity(); - } - - this.identify(); - } - - get settings() { - if (this._settings === undefined) { - this._settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup(Config.APP_ID, true), - }); - } - - return this._settings; - } - - vfunc_notify(pspec) { - if (pspec.name !== 'connection') - return; - - if (this.connection !== null) - this._exportDevices(); - else - this._unexportDevices(); - } - - /* - * GSettings - */ - _initSettings() { - // Initialize the ID and name of the service - if (this.settings.get_string('id').length === 0) - this.settings.set_string('id', GLib.uuid_string_random()); - - if (this.settings.get_string('name').length === 0) - this.settings.set_string('name', GLib.get_host_name()); - - // Bound Properties - this.settings.bind('discoverable', this, 'discoverable', 0); - this.settings.bind('id', this, 'id', 0); - this.settings.bind('name', this, 'name', 0); - } - - /* - * Backends - */ - _onChannel(backend, channel) { - try { - let device = this.devices.get(channel.identity.body.deviceId); - - switch (true) { - // Proceed if this is an existing device... - case (device !== undefined): - break; - - // Or the connection is allowed... - case this.discoverable || channel.allowed: - device = this._ensureDevice(channel.identity); - break; - - // ...otherwise bail - default: - debug(`${channel.identity.body.deviceName}: not allowed`); - return false; - } - - device.setChannel(channel); - return true; - } catch (e) { - logError(e, backend.name); - return false; - } - } - - _loadBackends() { - for (const name in backends) { - try { - const module = backends[name]; - - if (module.ChannelService === undefined) - continue; - - // Try to create the backend and track it if successful - const backend = new module.ChannelService({ - id: this.id, - name: this.name, - }); - this.backends.set(name, backend); - - // Connect to the backend - backend.__channelId = backend.connect( - 'channel', - this._onChannel.bind(this) - ); - - // Now try to start the backend, allowing us to retry if we fail - backend.start(); - } catch (e) { - if (Gio.Application.get_default()) - Gio.Application.get_default().notify_error(e); - } - } - } - - /* - * Devices - */ - _loadDevices() { - // Load cached devices - for (const id of this.settings.get_strv('devices')) { - const device = new Device({body: {deviceId: id}}); - this._exportDevice(device); - this.devices.set(id, device); - } - } - - _exportDevice(device) { - if (this.connection === null) - return; - - const info = { - object: null, - interface: null, - actions: 0, - menu: 0, - }; - - const objectPath = `${DEVICE_PATH}/${device.id.replace(/\W+/g, '_')}`; - - // Export an object path for the device - info.object = new Gio.DBusObjectSkeleton({ - g_object_path: objectPath, - }); - this.export(info.object); - - // Export GActions & GMenu - info.actions = Gio.DBus.session.export_action_group(objectPath, device); - info.menu = Gio.DBus.session.export_menu_model(objectPath, device.menu); - - // Export the Device interface - info.interface = new DBus.Interface({ - g_instance: device, - g_interface_info: DEVICE_IFACE, - }); - info.object.add_interface(info.interface); - - this._exported.set(device, info); - } - - _exportDevices() { - if (this.connection === null) - return; - - for (const device of this.devices.values()) - this._exportDevice(device); - } - - _unexportDevice(device) { - const info = this._exported.get(device); - - if (info === undefined) - return; - - // Unexport GActions and GMenu - Gio.DBus.session.unexport_action_group(info.actions); - Gio.DBus.session.unexport_menu_model(info.menu); - - // Unexport the Device interface and object - info.interface.flush(); - info.object.remove_interface(info.interface); - info.object.flush(); - this.unexport(info.object.g_object_path); - - this._exported.delete(device); - } - - _unexportDevices() { - for (const device of this.devices.values()) - this._unexportDevice(device); - } - - /** - * Return a device for @packet, creating it and adding it to the list of - * of known devices if it doesn't exist. - * - * @param {Core.Packet} packet - An identity packet for the device - * @return {Device} A device object - */ - _ensureDevice(packet) { - let device = this.devices.get(packet.body.deviceId); - - if (device === undefined) { - debug(`Adding ${packet.body.deviceName}`); - - // TODO: Remove when all clients support bluetooth-like discovery - // - // If this is the third unpaired device to connect, we disable - // discovery to avoid choking on networks with many devices - const unpaired = Array.from(this.devices.values()).filter(dev => { - return !dev.paired; - }); - - if (unpaired.length === 3) - this.discoverable = false; - - device = new Device(packet); - this._exportDevice(device); - this.devices.set(device.id, device); - - // Notify - this.settings.set_strv('devices', Array.from(this.devices.keys())); - } - - return device; - } - - /** - * Permanently remove a device. - * - * Removes the device from the list of known devices, deletes all GSettings - * and files. - * - * @param {string} id - The id of the device to delete - */ - _removeDevice(id) { - // Delete all GSettings - const settings_path = `/org/gnome/shell/extensions/gsconnect/${id}/`; - GLib.spawn_command_line_async(`dconf reset -f ${settings_path}`); - - // Delete the cache - const cache = GLib.build_filenamev([Config.CACHEDIR, id]); - Gio.File.rm_rf(cache); - - // Forget the device - this.devices.delete(id); - this.settings.set_strv('devices', Array.from(this.devices.keys())); - } - - /** - * A GSourceFunc that tries to reconnect to each paired device, while - * pruning unpaired devices that have disconnected. - * - * @return {boolean} Always %true - */ - _reconnect() { - for (const [id, device] of this.devices) { - if (device.connected) - continue; - - if (device.paired) { - this.identify(device.settings.get_string('last-connection')); - continue; - } - - this._unexportDevice(device); - this._removeDevice(id); - device.destroy(); - } - - return GLib.SOURCE_CONTINUE; - } - - /** - * Identify to an address or broadcast to the network. - * - * @param {string} [uri] - An address URI or %null to broadcast - */ - identify(uri = null) { - try { - // If we're passed a parameter, try and find a backend for it - if (uri !== null) { - const [scheme, address] = uri.split('://'); - - const backend = this.backends.get(scheme); - - if (backend !== undefined) - backend.broadcast(address); - - // If we're not discoverable, only try to reconnect known devices - } else if (!this.discoverable) { - this._reconnect(); - - // Otherwise have each backend broadcast to it's network - } else { - this.backends.forEach(backend => backend.broadcast()); - } - } catch (e) { - logError(e); - } - } - - /** - * Start managing devices. - */ - start() { - if (this.active) - return; - - this._loadDevices(); - this._loadBackends(); - - if (this._reconnectId === 0) { - this._reconnectId = GLib.timeout_add_seconds( - GLib.PRIORITY_LOW, - 5, - this._reconnect.bind(this) - ); - } - - this._active = true; - this.notify('active'); - } - - /** - * Stop managing devices. - */ - stop() { - if (!this.active) - return; - - if (this._reconnectId > 0) { - GLib.Source.remove(this._reconnectId); - this._reconnectId = 0; - } - - this._unexportDevices(); - - this.backends.forEach(backend => backend.destroy()); - this.backends.clear(); - - this.devices.forEach(device => device.destroy()); - this.devices.clear(); - - this._active = false; - this.notify('active'); - } - - /** - * Stop managing devices and free any resources. - */ - destroy() { - this.stop(); - this.set_connection(null); - } -}); - -export default Manager; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js deleted file mode 100755 index 297d180a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env -S gjs -m - -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio?version=2.0'; -import GLib from 'gi://GLib?version=2.0'; -import GObject from 'gi://GObject?version=2.0'; - -import system from 'system'; - -// Retain compatibility with GLib < 2.80, which lacks GioUnix -let GioUnix; -try { - GioUnix = (await import('gi://GioUnix?version=2.0')).default; -} catch (e) { - GioUnix = { - InputStream: Gio.UnixInputStream, - OutputStream: Gio.UnixOutputStream, - }; -} - - -const NativeMessagingHost = GObject.registerClass({ - GTypeName: 'GSConnectNativeMessagingHost', -}, class NativeMessagingHost extends Gio.Application { - - _init() { - super._init({ - application_id: 'org.gnome.Shell.Extensions.GSConnect.NativeMessagingHost', - flags: Gio.ApplicationFlags.NON_UNIQUE, - }); - } - - get devices() { - if (this._devices === undefined) - this._devices = {}; - - return this._devices; - } - - vfunc_activate() { - super.vfunc_activate(); - } - - vfunc_startup() { - super.vfunc_startup(); - this.hold(); - - // IO Channels - this._stdin = new Gio.DataInputStream({ - base_stream: new GioUnix.InputStream({fd: 0}), - byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN, - }); - - this._stdout = new Gio.DataOutputStream({ - base_stream: new GioUnix.OutputStream({fd: 1}), - byte_order: Gio.DataStreamByteOrder.HOST_ENDIAN, - }); - - const source = this._stdin.base_stream.create_source(null); - source.set_callback(this.receive.bind(this)); - source.attach(null); - - // Device Manager - try { - this._manager = Gio.DBusObjectManagerClient.new_for_bus_sync( - Gio.BusType.SESSION, - Gio.DBusObjectManagerClientFlags.DO_NOT_AUTO_START, - 'org.gnome.Shell.Extensions.GSConnect', - '/org/gnome/Shell/Extensions/GSConnect', - null, - null - ); - } catch (e) { - logError(e); - this.quit(); - } - - // Add currently managed devices - for (const object of this._manager.get_objects()) { - for (const iface of object.get_interfaces()) - this._onInterfaceAdded(this._manager, object, iface); - } - - // Watch for new and removed devices - this._manager.connect( - 'interface-added', - this._onInterfaceAdded.bind(this) - ); - this._manager.connect( - 'object-removed', - this._onObjectRemoved.bind(this) - ); - - // Watch for device property changes - this._manager.connect( - 'interface-proxy-properties-changed', - this.sendDeviceList.bind(this) - ); - - // Watch for service restarts - this._manager.connect( - 'notify::name-owner', - this.sendDeviceList.bind(this) - ); - - this.send({ - type: 'connected', - data: (this._manager.name_owner !== null), - }); - } - - receive() { - try { - // Read the message - const length = this._stdin.read_int32(null); - const bytes = this._stdin.read_bytes(length, null).toArray(); - const message = JSON.parse(new TextDecoder().decode(bytes)); - - // A request for a list of devices - if (message.type === 'devices') { - this.sendDeviceList(); - - // A request to invoke an action - } else if (message.type === 'share') { - let actionName; - const device = this.devices[message.data.device]; - - if (device) { - if (message.data.action === 'share') - actionName = 'shareUri'; - else if (message.data.action === 'telephony') - actionName = 'shareSms'; - - device.actions.activate_action( - actionName, - new GLib.Variant('s', message.data.url) - ); - } - } - - return GLib.SOURCE_CONTINUE; - } catch (e) { - this.quit(); - } - } - - send(message) { - try { - const data = JSON.stringify(message); - this._stdout.put_int32(data.length, null); - this._stdout.put_string(data, null); - } catch (e) { - this.quit(); - } - } - - sendDeviceList() { - // Inform the WebExtension we're disconnected from the service - if (this._manager && this._manager.name_owner === null) - return this.send({type: 'connected', data: false}); - - // Collect all the devices with supported actions - const available = []; - - for (const device of Object.values(this.devices)) { - const share = device.actions.get_action_enabled('shareUri'); - const telephony = device.actions.get_action_enabled('shareSms'); - - if (share || telephony) { - available.push({ - id: device.g_object_path, - name: device.name, - type: device.type, - share: share, - telephony: telephony, - }); - } - } - - this.send({type: 'devices', data: available}); - } - - _proxyGetter(name) { - try { - return this.get_cached_property(name).unpack(); - } catch (e) { - return null; - } - } - - _onInterfaceAdded(manager, object, iface) { - Object.defineProperties(iface, { - 'name': { - get: this._proxyGetter.bind(iface, 'Name'), - enumerable: true, - }, - // TODO: phase this out for icon-name - 'type': { - get: this._proxyGetter.bind(iface, 'Type'), - enumerable: true, - }, - }); - - iface.actions = Gio.DBusActionGroup.get( - iface.g_connection, - iface.g_name, - iface.g_object_path - ); - - this.devices[iface.g_object_path] = iface; - this.sendDeviceList(); - } - - _onObjectRemoved(manager, object) { - delete this.devices[object.g_object_path]; - this.sendDeviceList(); - } -}); - -// NOTE: must not pass ARGV -await (new NativeMessagingHost()).runAsync([system.programInvocationName]); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugin.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugin.js deleted file mode 100755 index ed2a5ef3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugin.js +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../config.js'; -import plugins from './plugins/index.js'; - - -/** - * Base class for device plugins. - */ -const Plugin = GObject.registerClass({ - GTypeName: 'GSConnectPlugin', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device that owns this plugin', - GObject.ParamFlags.READABLE, - GObject.Object - ), - 'name': GObject.ParamSpec.string( - 'name', - 'Name', - 'The device name', - GObject.ParamFlags.READABLE, - null - ), - }, -}, class Plugin extends GObject.Object { - - _init(device, name, meta = null) { - super._init(); - - this._device = device; - this._name = name; - this._meta = meta; - - if (this._meta === null) - this._meta = plugins[name].Metadata; - - // GSettings - const schema = Config.GSCHEMA.lookup(this._meta.id, false); - - if (schema !== null) { - this.settings = new Gio.Settings({ - settings_schema: schema, - path: `${device.settings.path}plugin/${name}/`, - }); - } - - // GActions - this._gactions = []; - - if (this._meta.actions) { - const menu = this.device.settings.get_strv('menu-actions'); - - for (const name in this._meta.actions) { - const info = this._meta.actions[name]; - this._registerAction(name, menu.indexOf(name), info); - } - } - } - - get cancellable() { - if (this._cancellable === undefined) - this._cancellable = new Gio.Cancellable(); - - return this._cancellable; - } - - get device() { - return this._device; - } - - get name() { - return this._name; - } - - _activateAction(action, parameter) { - try { - let args = null; - - if (parameter instanceof GLib.Variant) - args = parameter.full_unpack(); - - if (Array.isArray(args)) - this[action.name](...args); - else - this[action.name](args); - } catch (e) { - logError(e, action.name); - } - } - - _registerAction(name, menuIndex, info) { - try { - // Device Action - const action = new Gio.SimpleAction({ - name: name, - parameter_type: info.parameter_type, - enabled: false, - }); - action.connect('activate', this._activateAction.bind(this)); - - this.device.add_action(action); - - // Menu - if (menuIndex > -1) { - this.device.addMenuAction( - action, - menuIndex, - info.label, - info.icon_name - ); - } - - this._gactions.push(action); - } catch (e) { - logError(e, `${this.device.name}: ${this.name}`); - } - } - - /** - * Called when the device connects. - */ - connected() { - // Enabled based on device capabilities, which might change - const incoming = this.device.settings.get_strv('incoming-capabilities'); - const outgoing = this.device.settings.get_strv('outgoing-capabilities'); - - for (const action of this._gactions) { - const info = this._meta.actions[action.name]; - - if (info.incoming.every(type => outgoing.includes(type)) && - info.outgoing.every(type => incoming.includes(type))) - action.set_enabled(true); - } - } - - /** - * Called when the device disconnects. - */ - disconnected() { - for (const action of this._gactions) - action.set_enabled(false); - } - - /** - * Called when a packet is received that the plugin is a handler for. - * - * @param {Core.Packet} packet - A KDE Connect packet - */ - handlePacket(packet) { - throw new GObject.NotImplementedError(); - } - - /** - * Cache JSON parseable properties on this object for persistence. The - * filename ~/.cache/gsconnect/<device-id>/<plugin-name>.json will be used - * to store the properties and values. - * - * Calling cacheProperties() opens a JSON cache file and reads any stored - * properties and values onto the current instance. When destroy() - * is called the properties are automatically stored in the same file. - * - * @param {Array} names - A list of this object's property names to cache - */ - async cacheProperties(names) { - try { - this._cacheProperties = names; - - // Ensure the device's cache directory exists - const cachedir = GLib.build_filenamev([ - Config.CACHEDIR, - this.device.id, - ]); - GLib.mkdir_with_parents(cachedir, 448); - - this._cacheFile = Gio.File.new_for_path( - GLib.build_filenamev([cachedir, `${this.name}.json`])); - - // Read the cache from disk - const [contents] = await this._cacheFile.load_contents_async( - this.cancellable); - const cache = JSON.parse(new TextDecoder().decode(contents)); - Object.assign(this, cache); - } catch (e) { - debug(e.message, `${this.device.name}: ${this.name}`); - } finally { - this.cacheLoaded(); - } - } - - /** - * An overridable function that is invoked when the on-disk cache is being - * cleared. Implementations should use this function to clear any in-memory - * cache data. - */ - clearCache() {} - - /** - * An overridable function that is invoked when the cache is done loading - */ - cacheLoaded() {} - - /** - * Unregister plugin actions, write the cache (if applicable) and destroy - * any dangling signal handlers. - */ - destroy() { - // Cancel any pending plugin operations - if (this._cancellable !== undefined) - this._cancellable.cancel(); - - for (const action of this._gactions) { - this.device.removeMenuAction(`device.${action.name}`); - this.device.remove_action(action.name); - } - - // Write the cache to disk synchronously - if (this._cacheFile !== undefined) { - try { - // Build the cache - const cache = {}; - - for (const name of this._cacheProperties) - cache[name] = this[name]; - - this._cacheFile.replace_contents( - JSON.stringify(cache, null, 2), - null, - false, - Gio.FileCreateFlags.REPLACE_DESTINATION, - null - ); - } catch (e) { - debug(e.message, `${this.device.name}: ${this.name}`); - } - } - - GObject.signal_handlers_destroy(this); - } -}); - -export default Plugin; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/battery.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/battery.js deleted file mode 100755 index c7dbe042..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/battery.js +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Battery'), - description: _('Exchange battery information'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Battery', - incomingCapabilities: [ - 'kdeconnect.battery', - 'kdeconnect.battery.request', - ], - outgoingCapabilities: [ - 'kdeconnect.battery', - 'kdeconnect.battery.request', - ], - actions: {}, -}; - - -/** - * Battery Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/battery - */ -const BatteryPlugin = GObject.registerClass({ - GTypeName: 'GSConnectBatteryPlugin', -}, class BatteryPlugin extends Plugin { - - _init(device) { - super._init(device, 'battery'); - - // Setup Cache; defaults are 90 minute charge, 1 day discharge - this._chargeState = [54, 0, -1]; - this._dischargeState = [864, 0, -1]; - this._thresholdLevel = 25; - - this.cacheProperties([ - '_chargeState', - '_dischargeState', - '_thresholdLevel', - ]); - - // Export battery state as GAction - this.__state = new Gio.SimpleAction({ - name: 'battery', - parameter_type: new GLib.VariantType('(bsii)'), - state: this.state, - }); - this.device.add_action(this.__state); - - // Local Battery (UPower) - this._upower = null; - this._sendStatisticsId = this.settings.connect( - 'changed::send-statistics', - this._onSendStatisticsChanged.bind(this) - ); - this._onSendStatisticsChanged(this.settings); - } - - get charging() { - if (this._charging === undefined) - this._charging = false; - - return this._charging; - } - - get icon_name() { - let icon; - - if (this.level === -1) - return 'battery-missing-symbolic'; - else if (this.level === 100) - return 'battery-full-charged-symbolic'; - else if (this.level < 3) - icon = 'battery-empty'; - else if (this.level < 10) - icon = 'battery-caution'; - else if (this.level < 30) - icon = 'battery-low'; - else if (this.level < 60) - icon = 'battery-good'; - else if (this.level >= 60) - icon = 'battery-full'; - - if (this.charging) - return `${icon}-charging-symbolic`; - - return `${icon}-symbolic`; - } - - get level() { - // This is what KDE Connect returns if the remote battery plugin is - // disabled or still being loaded - if (this._level === undefined) - this._level = -1; - - return this._level; - } - - get time() { - if (this._time === undefined) - this._time = 0; - - return this._time; - } - - get state() { - return new GLib.Variant( - '(bsii)', - [this.charging, this.icon_name, this.level, this.time] - ); - } - - cacheLoaded() { - this._initEstimate(); - this._sendState(); - } - - clearCache() { - this._chargeState = [54, 0, -1]; - this._dischargeState = [864, 0, -1]; - this._thresholdLevel = 25; - this._initEstimate(); - } - - connected() { - super.connected(); - - this._requestState(); - this._sendState(); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.battery': - this._receiveState(packet); - break; - - case 'kdeconnect.battery.request': - this._sendState(); - break; - } - } - - _onSendStatisticsChanged() { - if (this.settings.get_boolean('send-statistics')) - this._monitorState(); - else - this._unmonitorState(); - } - - /** - * Recalculate and update the estimated time remaining, but not the rate. - */ - _initEstimate() { - let rate, level; - - // elision of [rate, time, level] - if (this.charging) - [rate,, level] = this._chargeState; - else - [rate,, level] = this._dischargeState; - - if (!Number.isFinite(rate) || rate < 1) - rate = this.charging ? 864 : 90; - - if (!Number.isFinite(level) || level < 0) - level = this.level; - - // Update the time remaining - if (rate && this.charging) - this._time = Math.floor(rate * (100 - level)); - else if (rate && !this.charging) - this._time = Math.floor(rate * level); - - this.__state.state = this.state; - } - - /** - * Recalculate the (dis)charge rate and update the estimated time remaining. - */ - _updateEstimate() { - let rate, time, level; - const newTime = Math.floor(Date.now() / 1000); - const newLevel = this.level; - - // Load the state; ensure we have sane values for calculation - if (this.charging) - [rate, time, level] = this._chargeState; - else - [rate, time, level] = this._dischargeState; - - if (!Number.isFinite(rate) || rate < 1) - rate = this.charging ? 54 : 864; - - if (!Number.isFinite(time) || time <= 0) - time = newTime; - - if (!Number.isFinite(level) || level < 0) - level = newLevel; - - // Update the rate; use a weighted average to account for missed changes - // NOTE: (rate = seconds/percent) - const ldiff = this.charging ? newLevel - level : level - newLevel; - const tdiff = newTime - time; - const newRate = tdiff / ldiff; - - if (newRate && Number.isFinite(newRate)) - rate = Math.floor((rate * 0.4) + (newRate * 0.6)); - - // Store the state for the next recalculation - if (this.charging) - this._chargeState = [rate, newTime, newLevel]; - else - this._dischargeState = [rate, newTime, newLevel]; - - // Update the time remaining - if (rate && this.charging) - this._time = Math.floor(rate * (100 - newLevel)); - else if (rate && !this.charging) - this._time = Math.floor(rate * newLevel); - - this.__state.state = this.state; - } - - /** - * Notify the user the remote battery is full. - */ - _fullBatteryNotification() { - if (!this.settings.get_boolean('full-battery-notification')) - return; - - // Offer the option to ring the device, if available - let buttons = []; - - if (this.device.get_action_enabled('ring')) { - buttons = [{ - label: _('Ring'), - action: 'ring', - parameter: null, - }]; - } - - this.device.showNotification({ - id: 'battery|full', - // TRANSLATORS: eg. Google Pixel: Battery is full - title: _('%s: Battery is full').format(this.device.name), - // TRANSLATORS: when the battery is fully charged - body: _('Fully Charged'), - icon: Gio.ThemedIcon.new('battery-full-charged-symbolic'), - buttons: buttons, - }); - } - - /** - * Notify the user the remote battery is at custom charge level. - */ - _customBatteryNotification() { - if (!this.settings.get_boolean('custom-battery-notification')) - return; - - // Offer the option to ring the device, if available - let buttons = []; - - if (this.device.get_action_enabled('ring')) { - buttons = [{ - label: _('Ring'), - action: 'ring', - parameter: null, - }]; - } - - this.device.showNotification({ - id: 'battery|custom', - // TRANSLATORS: eg. Google Pixel: Battery has reached custom charge level - title: _('%s: Battery has reached custom charge level').format(this.device.name), - // TRANSLATORS: when the battery has reached custom charge level - body: _('%d%% Charged').format(this.level), - icon: Gio.ThemedIcon.new('battery-full-charged-symbolic'), - buttons: buttons, - }); - } - - /** - * Notify the user the remote battery is low. - */ - _lowBatteryNotification() { - if (!this.settings.get_boolean('low-battery-notification')) - return; - - // Offer the option to ring the device, if available - let buttons = []; - - if (this.device.get_action_enabled('ring')) { - buttons = [{ - label: _('Ring'), - action: 'ring', - parameter: null, - }]; - } - - this.device.showNotification({ - id: 'battery|low', - // TRANSLATORS: eg. Google Pixel: Battery is low - title: _('%s: Battery is low').format(this.device.name), - // TRANSLATORS: eg. 15% remaining - body: _('%d%% remaining').format(this.level), - icon: Gio.ThemedIcon.new('battery-caution-symbolic'), - buttons: buttons, - }); - } - - /** - * Handle a remote battery update. - * - * @param {Core.Packet} packet - A kdeconnect.battery packet - */ - _receiveState(packet) { - // Charging state changed - this._charging = packet.body.isCharging; - - // Level changed - if (this._level !== packet.body.currentCharge) { - this._level = packet.body.currentCharge; - - // If the level is above the threshold hide the notification - if (this._level > this._thresholdLevel) - this.device.hideNotification('battery|low'); - - // The level just changed to/from custom level while charging - if ((this._level === this.settings.get_uint('custom-battery-notification-value')) && this._charging) - this._customBatteryNotification(); - else - this.device.hideNotification('battery|custom'); - - // The level just changed to/from full - if (this._level === 100) - this._fullBatteryNotification(); - else - this.device.hideNotification('battery|full'); - } - - // Device considers the level low - if (packet.body.thresholdEvent > 0) { - this._lowBatteryNotification(); - this._thresholdLevel = this.level; - } - - this._updateEstimate(); - } - - /** - * Request the remote battery's current state - */ - _requestState() { - this.device.sendPacket({ - type: 'kdeconnect.battery.request', - body: {request: true}, - }); - } - - /** - * Report the local battery's current state - */ - _sendState() { - if (this._upower === null || !this._upower.is_present) - return; - - this.device.sendPacket({ - type: 'kdeconnect.battery', - body: { - currentCharge: this._upower.level, - isCharging: this._upower.charging, - thresholdEvent: this._upower.threshold, - }, - }); - } - - /* - * UPower monitoring methods - */ - _monitorState() { - try { - // Currently only true if the remote device is a desktop (rare) - const incoming = this.device.settings.get_strv('incoming-capabilities'); - - if (!incoming.includes('kdeconnect.battery')) - return; - - this._upower = Components.acquire('upower'); - - this._upowerId = this._upower.connect( - 'changed', - this._sendState.bind(this) - ); - - this._sendState(); - } catch (e) { - logError(e, this.device.name); - this._unmonitorState(); - } - } - - _unmonitorState() { - try { - if (this._upower === null) - return; - - this._upower.disconnect(this._upowerId); - this._upower = Components.release('upower'); - } catch (e) { - logError(e, this.device.name); - } - } - - destroy() { - this.device.remove_action('battery'); - this.settings.disconnect(this._sendStatisticsId); - this._unmonitorState(); - - super.destroy(); - } -}); - -export default BatteryPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/clipboard.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/clipboard.js deleted file mode 100755 index 7a065747..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/clipboard.js +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Clipboard'), - description: _('Share the clipboard content'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Clipboard', - incomingCapabilities: [ - 'kdeconnect.clipboard', - 'kdeconnect.clipboard.connect', - ], - outgoingCapabilities: [ - 'kdeconnect.clipboard', - 'kdeconnect.clipboard.connect', - ], - actions: { - clipboardPush: { - label: _('Clipboard Push'), - icon_name: 'edit-paste-symbolic', - - parameter_type: null, - incoming: [], - outgoing: ['kdeconnect.clipboard'], - }, - clipboardPull: { - label: _('Clipboard Pull'), - icon_name: 'edit-copy-symbolic', - - parameter_type: null, - incoming: ['kdeconnect.clipboard'], - outgoing: [], - }, - }, -}; - - -/** - * Clipboard Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/clipboard - */ -const ClipboardPlugin = GObject.registerClass({ - GTypeName: 'GSConnectClipboardPlugin', -}, class ClipboardPlugin extends Plugin { - - _init(device) { - super._init(device, 'clipboard'); - - this._clipboard = Components.acquire('clipboard'); - - // Watch local clipboard for changes - this._textChangedId = this._clipboard.connect( - 'notify::text', - this._onLocalClipboardChanged.bind(this) - ); - - // Buffer content to allow selective sync - this._localBuffer = this._clipboard.text; - this._localTimestamp = 0; - this._remoteBuffer = null; - } - - connected() { - super.connected(); - - // TODO: if we're not auto-syncing local->remote, but we are doing the - // reverse, it's possible older remote content will end up - // overwriting newer local content. - if (!this.settings.get_boolean('send-content')) - return; - - if (this._localBuffer === null && this._localTimestamp === 0) - return; - - this.device.sendPacket({ - type: 'kdeconnect.clipboard.connect', - body: { - content: this._localBuffer, - timestamp: this._localTimestamp, - }, - }); - } - - handlePacket(packet) { - if (!packet.body.hasOwnProperty('content')) - return; - - switch (packet.type) { - case 'kdeconnect.clipboard': - this._handleContent(packet); - break; - - case 'kdeconnect.clipboard.connect': - this._handleConnectContent(packet); - break; - } - } - - _handleContent(packet) { - this._onRemoteClipboardChanged(packet.body.content); - } - - _handleConnectContent(packet) { - if (packet.body.hasOwnProperty('timestamp') && - packet.body.timestamp > this._localTimestamp) - this._onRemoteClipboardChanged(packet.body.content); - } - - /* - * Store the local clipboard content and forward it if enabled - */ - _onLocalClipboardChanged(clipboard, pspec) { - this._localBuffer = clipboard.text; - this._localTimestamp = Date.now(); - - if (this.settings.get_boolean('send-content')) - this.clipboardPush(); - } - - /* - * Store the remote clipboard content and apply it if enabled - */ - _onRemoteClipboardChanged(text) { - this._remoteBuffer = text; - - if (this.settings.get_boolean('receive-content')) - this.clipboardPull(); - } - - /** - * Copy to the remote clipboard; called by _onLocalClipboardChanged() - */ - clipboardPush() { - // Don't sync if the clipboard is empty or not text - if (this._localTimestamp === 0) - return; - - if (this._remoteBuffer !== this._localBuffer) { - this._remoteBuffer = this._localBuffer; - - // If the buffer is %null, the clipboard contains non-text content, - // so we neither clear the remote clipboard nor pass the content - if (this._localBuffer !== null) { - this.device.sendPacket({ - type: 'kdeconnect.clipboard', - body: { - content: this._localBuffer, - }, - }); - } - } - } - - /** - * Copy from the remote clipboard; called by _onRemoteClipboardChanged() - */ - clipboardPull() { - if (this._localBuffer !== this._remoteBuffer) { - this._localBuffer = this._remoteBuffer; - this._localTimestamp = Date.now(); - - this._clipboard.text = this._remoteBuffer; - } - } - - destroy() { - if (this._clipboard && this._textChangedId) { - this._clipboard.disconnect(this._textChangedId); - this._clipboard = Components.release('clipboard'); - } - - super.destroy(); - } -}); - -export default ClipboardPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/connectivity_report.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/connectivity_report.js deleted file mode 100755 index 7107ff7a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/connectivity_report.js +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Connectivity Report'), - description: _('Display connectivity status'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.ConnectivityReport', - incomingCapabilities: [ - 'kdeconnect.connectivity_report', - ], - outgoingCapabilities: [ - 'kdeconnect.connectivity_report.request', - ], - actions: {}, -}; - - -/** - * Connectivity Report Plugin - * https://invent.kde.org/network/kdeconnect-kde/-/tree/master/plugins/connectivity_report - */ -const ConnectivityReportPlugin = GObject.registerClass({ - GTypeName: 'GSConnectConnectivityReportPlugin', -}, class ConnectivityReportPlugin extends Plugin { - - _init(device) { - super._init(device, 'connectivity_report'); - - // Export connectivity state as GAction - this.__state = new Gio.SimpleAction({ - name: 'connectivityReport', - // ( - // cellular_network_type, - // cellular_network_type_icon, - // cellular_network_strength(0..4), - // cellular_network_strength_icon, - // ) - parameter_type: new GLib.VariantType('(ssis)'), - state: this.state, - }); - this.device.add_action(this.__state); - } - - get signal_strength() { - if (this._signalStrength === undefined) - this._signalStrength = -1; - - return this._signalStrength; - } - - get network_type() { - if (this._networkType === undefined) - this._networkType = ''; - - return this._networkType; - } - - get signal_strength_icon_name() { - if (this.signal_strength === 0) - return 'network-cellular-signal-none-symbolic'; // SIGNAL_STRENGTH_NONE_OR_UNKNOWN - else if (this.signal_strength === 1) - return 'network-cellular-signal-weak-symbolic'; // SIGNAL_STRENGTH_POOR - else if (this.signal_strength === 2) - return 'network-cellular-signal-ok-symbolic'; // SIGNAL_STRENGTH_MODERATE - else if (this.signal_strength === 3) - return 'network-cellular-signal-good-symbolic'; // SIGNAL_STRENGTH_GOOD - else if (this.signal_strength >= 4) - return 'network-cellular-signal-excellent-symbolic'; // SIGNAL_STRENGTH_GREAT - - return 'network-cellular-offline-symbolic'; // OFF (signal_strength == -1) - } - - get network_type_icon_name() { - if (this.network_type === 'GSM' || this.network_type === 'CDMA' || this.network_type === 'iDEN') - return 'network-cellular-2g-symbolic'; - else if (this.network_type === 'UMTS' || this.network_type === 'CDMA2000') - return 'network-cellular-3g-symbolic'; - else if (this.network_type === 'LTE') - return 'network-cellular-4g-symbolic'; - else if (this.network_type === 'EDGE') - return 'network-cellular-edge-symbolic'; - else if (this.network_type === 'GPRS') - return 'network-cellular-gprs-symbolic'; - else if (this.network_type === 'HSPA') - return 'network-cellular-hspa-symbolic'; - else if (this.network_type === '5G') - return 'network-cellular-5g-symbolic'; - - return 'network-cellular-symbolic'; - } - - get state() { - return new GLib.Variant( - '(ssis)', - [ - this.network_type, - this.network_type_icon_name, - this.signal_strength, - this.signal_strength_icon_name, - ] - ); - } - - connected() { - super.connected(); - - this._requestState(); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.connectivity_report': - this._receiveState(packet); - break; - } - } - - /** - * Handle a remote state update. - * - * @param {Core.Packet} packet - A kdeconnect.connectivity_report packet - */ - _receiveState(packet) { - if (packet.body.signalStrengths) { - // TODO: Only first SIM (subscriptionID) is supported at the moment - const subs = Object.keys(packet.body.signalStrengths); - const firstSub = Math.min.apply(null, subs); - const data = packet.body.signalStrengths[firstSub]; - - this._networkType = data.networkType; - this._signalStrength = data.signalStrength; - } - - // Update DBus state - this.__state.state = this.state; - } - - /** - * Request the remote device's connectivity state - */ - _requestState() { - this.device.sendPacket({ - type: 'kdeconnect.connectivity_report.request', - body: {}, - }); - } - - destroy() { - this.device.remove_action('connectivity_report'); - - super.destroy(); - } -}); - -export default ConnectivityReportPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/contacts.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/contacts.js deleted file mode 100755 index 21687127..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/contacts.js +++ /dev/null @@ -1,463 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Plugin from '../plugin.js'; -import Contacts from '../components/contacts.js'; - -/* - * We prefer libebook's vCard parser if it's available - */ -let EBookContacts; -export const setEBookContacts = (ebook) => { // This function is only for tests to call! - EBookContacts = ebook; -}; - -try { - EBookContacts = (await import('gi://EBookContacts')).default; -} catch (e) { - EBookContacts = null; -} - - -export const Metadata = { - label: _('Contacts'), - description: _('Access contacts of the paired device'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Contacts', - incomingCapabilities: [ - 'kdeconnect.contacts.response_uids_timestamps', - 'kdeconnect.contacts.response_vcards', - ], - outgoingCapabilities: [ - 'kdeconnect.contacts.request_all_uids_timestamps', - 'kdeconnect.contacts.request_vcards_by_uid', - ], - actions: {}, -}; - - -/* - * vCard 2.1 Patterns - */ -const VCARD_FOLDING = /\r\n |\r |\n |=\n/g; -const VCARD_SUPPORTED = /^fn|tel|photo|x-kdeconnect/i; -const VCARD_BASIC = /^([^:;]+):(.+)$/; -const VCARD_TYPED = /^([^:;]+);([^:]+):(.+)$/; -const VCARD_TYPED_KEY = /item\d{1,2}\./; -const VCARD_TYPED_META = /([a-z]+)=(.*)/i; - - -/** - * Contacts Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/contacts - */ -const ContactsPlugin = GObject.registerClass({ - GTypeName: 'GSConnectContactsPlugin', -}, class ContactsPlugin extends Plugin { - - _init(device) { - super._init(device, 'contacts'); - - this._store = new Contacts(device.id); - this._store.fetch = this._requestUids.bind(this); - - // Notify when the store is ready - this._contactsStoreReadyId = this._store.connect( - 'notify::context', - () => this.device.notify('contacts') - ); - - // Notify if the contacts source changes - this._contactsSourceChangedId = this.settings.connect( - 'changed::contacts-source', - () => this.device.notify('contacts') - ); - - // Load the cache - this._store.load(); - } - - clearCache() { - this._store.clear(); - } - - connected() { - super.connected(); - this._requestUids(); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.contacts.response_uids_timestamps': - this._handleUids(packet); - break; - - case 'kdeconnect.contacts.response_vcards': - this._handleVCards(packet); - break; - } - } - - _handleUids(packet) { - try { - const contacts = this._store.contacts; - const remote_uids = packet.body.uids; - let removed = false; - delete packet.body.uids; - - // Usually a failed request, so avoid wiping the cache - if (remote_uids.length === 0) - return; - - // Delete any contacts that were removed on the device - for (let i = 0, len = contacts.length; i < len; i++) { - const contact = contacts[i]; - - if (!remote_uids.includes(contact.id)) { - this._store.remove(contact.id, false); - removed = true; - } - } - - // Build a list of new or updated contacts - const uids = []; - - for (const [uid, timestamp] of Object.entries(packet.body)) { - const contact = this._store.get_contact(uid); - - if (!contact || contact.timestamp !== timestamp) - uids.push(uid); - } - - // Send a request for any new or updated contacts - if (uids.length) - this._requestVCards(uids); - - // If we removed any contacts, save the cache - if (removed) - this._store.save(); - } catch (e) { - logError(e); - } - } - - /** - * Decode a string encoded as "QUOTED-PRINTABLE" and return a regular string - * - * See: https://github.com/mathiasbynens/quoted-printable/blob/master/src/quoted-printable.js - * - * @param {string} input - The QUOTED-PRINTABLE string - * @return {string} The decoded string - */ - _decodeQuotedPrintable(input) { - return input - // https://tools.ietf.org/html/rfc2045#section-6.7, rule 3 - .replace(/[\t\x20]$/gm, '') - // Remove hard line breaks preceded by `=` - .replace(/=(?:\r\n?|\n|$)/g, '') - // https://tools.ietf.org/html/rfc2045#section-6.7, note 1. - .replace(/=([a-fA-F0-9]{2})/g, ($0, $1) => { - const codePoint = parseInt($1, 16); - return String.fromCharCode(codePoint); - }); - } - - /** - * Decode a string encoded as "UTF-8" and return a regular string - * - * See: https://github.com/kvz/locutus/blob/master/src/php/xml/utf8_decode.js - * - * @param {string} input - The UTF-8 string - * @return {string} The decoded string - */ - _decodeUTF8(input) { - try { - const output = []; - let i = 0; - let c1 = 0; - let seqlen = 0; - - while (i < input.length) { - c1 = input.charCodeAt(i) & 0xFF; - seqlen = 0; - - if (c1 <= 0xBF) { - c1 &= 0x7F; - seqlen = 1; - } else if (c1 <= 0xDF) { - c1 &= 0x1F; - seqlen = 2; - } else if (c1 <= 0xEF) { - c1 &= 0x0F; - seqlen = 3; - } else { - c1 &= 0x07; - seqlen = 4; - } - - for (let ai = 1; ai < seqlen; ++ai) - c1 = ((c1 << 0x06) | (input.charCodeAt(ai + i) & 0x3F)); - - if (seqlen === 4) { - c1 -= 0x10000; - output.push(String.fromCharCode(0xD800 | ((c1 >> 10) & 0x3FF))); - output.push(String.fromCharCode(0xDC00 | (c1 & 0x3FF))); - } else { - output.push(String.fromCharCode(c1)); - } - - i += seqlen; - } - - return output.join(''); - - // Fallback to old unfaithful - } catch (e) { - try { - return decodeURIComponent(escape(input)); - - // Say "chowdah" frenchie! - } catch (e) { - debug(e, `Failed to decode UTF-8 VCard field ${input}`); - return input; - } - } - } - - /** - * Parse a vCard (v2.1 only) and return a dictionary of the fields - * - * See: http://jsfiddle.net/ARTsinn/P2t2P/ - * - * @param {string} vcard_data - The raw VCard data - * @return {Object} dictionary of vCard data - */ - _parseVCard21(vcard_data) { - // vcard skeleton - const vcard = { - fn: _('Unknown Contact'), - tel: [], - }; - - // Remove line folding and split - const unfolded = vcard_data.replace(VCARD_FOLDING, ''); - const lines = unfolded.split(/\r\n|\r|\n/); - - for (let i = 0, len = lines.length; i < len; i++) { - const line = lines[i]; - let results, key, type, value; - - // Empty line or a property we aren't interested in - if (!line || !line.match(VCARD_SUPPORTED)) - continue; - - // Basic Fields (fn, x-kdeconnect-timestamp, etc) - if ((results = line.match(VCARD_BASIC))) { - [, key, value] = results; - vcard[key.toLowerCase()] = value; - continue; - } - - // Typed Fields (tel, adr, etc) - if ((results = line.match(VCARD_TYPED))) { - [, key, type, value] = results; - key = key.replace(VCARD_TYPED_KEY, '').toLowerCase(); - value = value.split(';'); - type = type.split(';'); - - // Type(s) - const meta = {}; - - for (let i = 0, len = type.length; i < len; i++) { - const res = type[i].match(VCARD_TYPED_META); - - if (res) - meta[res[1]] = res[2]; - else - meta[`type${i === 0 ? '' : i}`] = type[i].toLowerCase(); - } - - // Value(s) - if (vcard[key] === undefined) - vcard[key] = []; - - // Decode QUOTABLE-PRINTABLE - if (meta.ENCODING && meta.ENCODING === 'QUOTED-PRINTABLE') { - delete meta.ENCODING; - value = value.map(v => this._decodeQuotedPrintable(v)); - } - - // Decode UTF-8 - if (meta.CHARSET && meta.CHARSET === 'UTF-8') { - delete meta.CHARSET; - value = value.map(v => this._decodeUTF8(v)); - } - - // Special case for FN (full name) - if (key === 'fn') - vcard[key] = value[0]; - else - vcard[key].push({meta: meta, value: value}); - } - } - - return vcard; - } - - /** - * Parse a vCard (v2.1 only) using native JavaScript and add it to the - * contact store. - * - * @param {string} uid - The contact UID - * @param {string} vcard_data - The raw vCard data - */ - async _parseVCardNative(uid, vcard_data) { - try { - const vcard = this._parseVCard21(vcard_data); - - const contact = { - id: uid, - name: vcard.fn, - numbers: [], - origin: 'device', - timestamp: parseInt(vcard['x-kdeconnect-timestamp']), - }; - - // Phone Numbers - contact.numbers = vcard.tel.map(entry => { - let type = 'unknown'; - - if (entry.meta && entry.meta.type) - type = entry.meta.type; - - return {type: type, value: entry.value[0]}; - }); - - // Avatar - if (vcard.photo) { - const data = GLib.base64_decode(vcard.photo[0].value[0]); - contact.avatar = await this._store.storeAvatar(data); - } - - this._store.add(contact); - } catch (e) { - debug(e, `Failed to parse VCard contact ${uid}`); - } - } - - /** - * Parse a vCard using libebook and add it to the contact store. - * - * @param {string} uid - The contact UID - * @param {string} vcard_data - The raw vCard data - */ - async _parseVCard(uid, vcard_data) { - try { - const contact = { - id: uid, - name: _('Unknown Contact'), - numbers: [], - origin: 'device', - timestamp: 0, - }; - - const evcard = EBookContacts.VCard.new_from_string(vcard_data); - const attrs = evcard.get_attributes(); - - for (let i = 0, len = attrs.length; i < len; i++) { - const attr = attrs[i]; - let data, number; - - switch (attr.get_name().toLowerCase()) { - case 'fn': - contact.name = attr.get_value(); - break; - - case 'tel': - number = {value: attr.get_value(), type: 'unknown'}; - - if (attr.has_type('CELL')) - number.type = 'cell'; - else if (attr.has_type('HOME')) - number.type = 'home'; - else if (attr.has_type('WORK')) - number.type = 'work'; - - contact.numbers.push(number); - break; - - case 'x-kdeconnect-timestamp': - contact.timestamp = parseInt(attr.get_value()); - break; - - case 'photo': - data = GLib.base64_decode(attr.get_value()); - contact.avatar = await this._store.storeAvatar(data); - break; - } - } - - this._store.add(contact); - } catch (e) { - debug(e, `Failed to parse VCard contact ${uid}`); - } - } - - /** - * Handle an incoming list of contact vCards and pass them to the best - * available parser. - * - * @param {Core.Packet} packet - A `kdeconnect.contacts.response_vcards` - */ - _handleVCards(packet) { - try { - // We don't use this - delete packet.body.uids; - - // Parse each vCard and add the contact - for (const [uid, vcard] of Object.entries(packet.body)) { - if (EBookContacts) - this._parseVCard(uid, vcard); - else - this._parseVCardNative(uid, vcard); - } - } catch (e) { - logError(e, this.device.name); - } - } - - /** - * Request a list of contact UIDs with timestamps. - */ - _requestUids() { - this.device.sendPacket({ - type: 'kdeconnect.contacts.request_all_uids_timestamps', - }); - } - - /** - * Request the vCards for @uids. - * - * @param {string[]} uids - A list of contact UIDs - */ - _requestVCards(uids) { - this.device.sendPacket({ - type: 'kdeconnect.contacts.request_vcards_by_uid', - body: { - uids: uids, - }, - }); - } - - destroy() { - this._store.disconnect(this._contactsStoreReadyId); - this.settings.disconnect(this._contactsSourceChangedId); - - super.destroy(); - } -}); - -export default ContactsPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/findmyphone.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/findmyphone.js deleted file mode 100755 index b5226bb9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/findmyphone.js +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import * as Components from '../components/index.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Find My Phone'), - description: _('Ring your paired device'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.FindMyPhone', - incomingCapabilities: ['kdeconnect.findmyphone.request'], - outgoingCapabilities: ['kdeconnect.findmyphone.request'], - actions: { - ring: { - label: _('Ring'), - icon_name: 'phonelink-ring-symbolic', - - parameter_type: null, - incoming: [], - outgoing: ['kdeconnect.findmyphone.request'], - }, - }, -}; - - -/** - * FindMyPhone Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/findmyphone - */ -const FindMyPhonePlugin = GObject.registerClass({ - GTypeName: 'GSConnectFindMyPhonePlugin', -}, class FindMyPhonePlugin extends Plugin { - - _init(device) { - super._init(device, 'findmyphone'); - - this._dialog = null; - this._player = Components.acquire('sound'); - this._mixer = Components.acquire('pulseaudio'); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.findmyphone.request': - this._handleRequest(); - break; - } - } - - /** - * Handle an incoming location request. - */ - _handleRequest() { - try { - // If this is a second request, stop announcing and return - if (this._dialog !== null) { - this._dialog.response(Gtk.ResponseType.DELETE_EVENT); - return; - } - - this._dialog = new Dialog({ - device: this.device, - plugin: this, - }); - - this._dialog.connect('response', () => { - this._dialog = null; - }); - } catch (e) { - this._cancelRequest(); - logError(e, this.device.name); - } - } - - /** - * Cancel any ongoing ringing and destroy the dialog. - */ - _cancelRequest() { - if (this._dialog !== null) - this._dialog.response(Gtk.ResponseType.DELETE_EVENT); - } - - /** - * Request that the remote device announce it's location - */ - ring() { - this.device.sendPacket({ - type: 'kdeconnect.findmyphone.request', - body: {}, - }); - } - - destroy() { - this._cancelRequest(); - - if (this._mixer !== undefined) - this._mixer = Components.release('pulseaudio'); - - if (this._player !== undefined) - this._player = Components.release('sound'); - - super.destroy(); - } -}); - - -/* - * Used to ensure 'audible-bell' is enabled for fallback - */ -const _WM_SETTINGS = new Gio.Settings({ - schema_id: 'org.gnome.desktop.wm.preferences', - path: '/org/gnome/desktop/wm/preferences/', -}); - - -/** - * A custom GtkMessageDialog for alerting of incoming requests - */ -const Dialog = GObject.registerClass({ - GTypeName: 'GSConnectFindMyPhoneDialog', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The plugin providing messages', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - }, -}, class Dialog extends Gtk.MessageDialog { - _init(params) { - super._init({ - buttons: Gtk.ButtonsType.CLOSE, - device: params.device, - image: new Gtk.Image({ - icon_name: 'phonelink-ring-symbolic', - pixel_size: 512, - halign: Gtk.Align.CENTER, - hexpand: true, - valign: Gtk.Align.CENTER, - vexpand: true, - visible: true, - }), - plugin: params.plugin, - urgency_hint: true, - }); - - this.set_keep_above(true); - this.maximize(); - this.message_area.destroy(); - - // If an output stream is available start fading the volume up - if (this.plugin._mixer && this.plugin._mixer.output) { - this._stream = this.plugin._mixer.output; - - this._previousMuted = this._stream.muted; - this._previousVolume = this._stream.volume; - - this._stream.muted = false; - this._stream.fade(0.85, 15); - - // Otherwise ensure audible-bell is enabled - } else { - this._previousBell = _WM_SETTINGS.get_boolean('audible-bell'); - _WM_SETTINGS.set_boolean('audible-bell', true); - } - - // Start the alarm - if (this.plugin._player !== undefined) - this.plugin._player.loopSound('phone-incoming-call', this.cancellable); - - // Show the dialog - this.show_all(); - } - - vfunc_key_press_event(event) { - this.response(Gtk.ResponseType.DELETE_EVENT); - - return Gdk.EVENT_STOP; - } - - vfunc_motion_notify_event(event) { - this.response(Gtk.ResponseType.DELETE_EVENT); - - return Gdk.EVENT_STOP; - } - - vfunc_response(response_id) { - // Stop the alarm - this.cancellable.cancel(); - - // Restore the mixer level - if (this._stream) { - this._stream.muted = this._previousMuted; - this._stream.fade(this._previousVolume); - - // Restore the audible-bell - } else { - _WM_SETTINGS.set_boolean('audible-bell', this._previousBell); - } - - this.destroy(); - } - - get cancellable() { - if (this._cancellable === undefined) - this._cancellable = new Gio.Cancellable(); - - return this._cancellable; - } - - get device() { - if (this._device === undefined) - this._device = null; - - return this._device; - } - - set device(device) { - this._device = device; - } - - get plugin() { - if (this._plugin === undefined) - this._plugin = null; - - return this._plugin; - } - - set plugin(plugin) { - this._plugin = plugin; - } -}); - -export default FindMyPhonePlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/index.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/index.js deleted file mode 100755 index 3d304a04..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/index.js +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import * as battery from './battery.js'; -import * as clipboard from './clipboard.js'; -import * as connectivity_report from './connectivity_report.js'; -import * as contacts from './contacts.js'; -import * as findmyphone from './findmyphone.js'; -import * as mousepad from './mousepad.js'; -import * as mpris from './mpris.js'; -import * as notification from './notification.js'; -import * as ping from './ping.js'; -import * as presenter from './presenter.js'; -import * as runcommand from './runcommand.js'; -import * as sftp from './sftp.js'; -import * as share from './share.js'; -import * as sms from './sms.js'; -import * as systemvolume from './systemvolume.js'; -import * as telephony from './telephony.js'; - -export default { - battery, - clipboard, - connectivity_report, - contacts, - findmyphone, - mousepad, - mpris, - notification, - ping, - presenter, - runcommand, - sftp, - share, - sms, - systemvolume, - telephony, -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/mousepad.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/mousepad.js deleted file mode 100755 index a4e40aed..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/mousepad.js +++ /dev/null @@ -1,381 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import {InputDialog} from '../ui/mousepad.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Mousepad'), - description: _('Enables the paired device to act as a remote mouse and keyboard'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Mousepad', - incomingCapabilities: [ - 'kdeconnect.mousepad.echo', - 'kdeconnect.mousepad.request', - 'kdeconnect.mousepad.keyboardstate', - ], - outgoingCapabilities: [ - 'kdeconnect.mousepad.echo', - 'kdeconnect.mousepad.request', - 'kdeconnect.mousepad.keyboardstate', - ], - actions: { - keyboard: { - label: _('Remote Input'), - icon_name: 'input-keyboard-symbolic', - - parameter_type: null, - incoming: [ - 'kdeconnect.mousepad.echo', - 'kdeconnect.mousepad.keyboardstate', - ], - outgoing: ['kdeconnect.mousepad.request'], - }, - }, -}; - -/** - * A map of "KDE Connect" keyvals to Gdk - */ -const KeyMap = new Map([ - [1, Gdk.KEY_BackSpace], - [2, Gdk.KEY_Tab], - [3, Gdk.KEY_Linefeed], - [4, Gdk.KEY_Left], - [5, Gdk.KEY_Up], - [6, Gdk.KEY_Right], - [7, Gdk.KEY_Down], - [8, Gdk.KEY_Page_Up], - [9, Gdk.KEY_Page_Down], - [10, Gdk.KEY_Home], - [11, Gdk.KEY_End], - [12, Gdk.KEY_Return], - [13, Gdk.KEY_Delete], - [14, Gdk.KEY_Escape], - [15, Gdk.KEY_Sys_Req], - [16, Gdk.KEY_Scroll_Lock], - [17, 0], - [18, 0], - [19, 0], - [20, 0], - [21, Gdk.KEY_F1], - [22, Gdk.KEY_F2], - [23, Gdk.KEY_F3], - [24, Gdk.KEY_F4], - [25, Gdk.KEY_F5], - [26, Gdk.KEY_F6], - [27, Gdk.KEY_F7], - [28, Gdk.KEY_F8], - [29, Gdk.KEY_F9], - [30, Gdk.KEY_F10], - [31, Gdk.KEY_F11], - [32, Gdk.KEY_F12], -]); - -const KeyMapCodes = new Map([ - [1, 14], - [2, 15], - [3, 101], - [4, 105], - [5, 103], - [6, 106], - [7, 108], - [8, 104], - [9, 109], - [10, 102], - [11, 107], - [12, 28], - [13, 111], - [14, 1], - [15, 99], - [16, 70], - [17, 0], - [18, 0], - [19, 0], - [20, 0], - [21, 59], - [22, 60], - [23, 61], - [24, 62], - [25, 63], - [26, 64], - [27, 65], - [28, 66], - [29, 67], - [30, 68], - [31, 87], - [32, 88], -]); - -/** - * Mousepad Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/mousepad - * - * TODO: support outgoing mouse events? - */ -const MousepadPlugin = GObject.registerClass({ - GTypeName: 'GSConnectMousepadPlugin', - Properties: { - 'state': GObject.ParamSpec.boolean( - 'state', - 'State', - 'Remote keyboard state', - GObject.ParamFlags.READABLE, - false - ), - }, -}, class MousepadPlugin extends Plugin { - _init(device) { - super._init(device, 'mousepad'); - - if (!globalThis.HAVE_GNOME) - this._input = Components.acquire('ydotool'); - else - this._input = Components.acquire('input'); - - this._shareControlChangedId = this.settings.connect( - 'changed::share-control', - this._sendState.bind(this) - ); - } - - get state() { - if (this._state === undefined) - this._state = false; - - return this._state; - } - - connected() { - super.connected(); - - this._sendState(); - } - - disconnected() { - super.disconnected(); - - this._state = false; - this.notify('state'); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.mousepad.request': - this._handleInput(packet.body); - break; - - case 'kdeconnect.mousepad.echo': - this._handleEcho(packet.body); - break; - - case 'kdeconnect.mousepad.keyboardstate': - this._handleState(packet); - break; - } - } - - /** - * Handle a input event. - * - * @param {Object} input - The body of a `kdeconnect.mousepad.request` - */ - _handleInput(input) { - if (!this.settings.get_boolean('share-control')) - return; - - let keysym; - let modifiers = 0; - const modifiers_codes = []; - - // These are ordered, as much as possible, to create the shortest code - // path for high-frequency, low-latency events (eg. mouse movement) - switch (true) { - case input.hasOwnProperty('scroll'): - this._input.scrollPointer(input.dx, input.dy); - break; - - case (input.hasOwnProperty('dx') && input.hasOwnProperty('dy')): - this._input.movePointer(input.dx, input.dy); - break; - - case (input.hasOwnProperty('key') || input.hasOwnProperty('specialKey')): - // NOTE: \u0000 sometimes sent in advance of a specialKey packet - if (input.key && input.key === '\u0000') - return; - - // Modifiers - if (input.alt) { - modifiers |= Gdk.ModifierType.MOD1_MASK; - modifiers_codes.push(56); - } - - if (input.ctrl) { - modifiers |= Gdk.ModifierType.CONTROL_MASK; - modifiers_codes.push(29); - } - - if (input.shift) { - modifiers |= Gdk.ModifierType.SHIFT_MASK; - modifiers_codes.push(42); - } - - if (input.super) { - modifiers |= Gdk.ModifierType.SUPER_MASK; - modifiers_codes.push(125); - } - - // Regular key (printable ASCII or Unicode) - if (input.key) { - if (!globalThis.HAVE_GNOME) - this._input.pressKeys(input.key, modifiers_codes); - else - this._input.pressKeys(input.key, modifiers); - - this._sendEcho(input); - - // Special key (eg. non-printable ASCII) - } else if (input.specialKey && KeyMap.has(input.specialKey)) { - if (!globalThis.HAVE_GNOME) { - keysym = KeyMapCodes.get(input.specialKey); - this._input.pressKeys(keysym, modifiers_codes); - } else { - keysym = KeyMap.get(input.specialKey); - this._input.pressKeys(keysym, modifiers); - } - - this._sendEcho(input); - } - break; - - case input.hasOwnProperty('singleclick'): - this._input.clickPointer(Gdk.BUTTON_PRIMARY); - break; - - case input.hasOwnProperty('doubleclick'): - this._input.doubleclickPointer(Gdk.BUTTON_PRIMARY); - break; - - case input.hasOwnProperty('middleclick'): - this._input.clickPointer(Gdk.BUTTON_MIDDLE); - break; - - case input.hasOwnProperty('rightclick'): - this._input.clickPointer(Gdk.BUTTON_SECONDARY); - break; - - case input.hasOwnProperty('singlehold'): - this._input.pressPointer(Gdk.BUTTON_PRIMARY); - break; - - case input.hasOwnProperty('singlerelease'): - this._input.releasePointer(Gdk.BUTTON_PRIMARY); - break; - - default: - logError(new Error('Unknown input')); - } - } - - /** - * Handle an echo/ACK of a event we sent, displaying it the dialog entry. - * - * @param {Object} input - The body of a `kdeconnect.mousepad.echo` - */ - _handleEcho(input) { - if (!this._dialog || !this._dialog.visible) - return; - - // Skip modifiers - if (input.alt || input.ctrl || input.super) - return; - - if (input.key) { - this._dialog._isAck = true; - this._dialog.entry.buffer.text += input.key; - this._dialog._isAck = false; - } else if (KeyMap.get(input.specialKey) === Gdk.KEY_BackSpace) { - this._dialog.entry.emit('backspace'); - } - } - - /** - * Handle a state change from the remote keyboard. This is an indication - * that the remote keyboard is ready to accept input. - * - * @param {Object} packet - A `kdeconnect.mousepad.keyboardstate` packet - */ - _handleState(packet) { - this._state = !!packet.body.state; - this.notify('state'); - } - - /** - * Send an echo/ACK of @input, if requested - * - * @param {Object} input - The body of a 'kdeconnect.mousepad.request' - */ - _sendEcho(input) { - if (!input.sendAck) - return; - - delete input.sendAck; - input.isAck = true; - - this.device.sendPacket({ - type: 'kdeconnect.mousepad.echo', - body: input, - }); - } - - /** - * Send the local keyboard state - * - * @param {boolean} state - Whether we're ready to accept input - */ - _sendState() { - this.device.sendPacket({ - type: 'kdeconnect.mousepad.keyboardstate', - body: { - state: this.settings.get_boolean('share-control'), - }, - }); - } - - /** - * Open the Keyboard Input dialog - */ - keyboard() { - if (this._dialog === undefined) { - this._dialog = new InputDialog({ - device: this.device, - plugin: this, - }); - } - - this._dialog.present(); - } - - destroy() { - if (this._input !== undefined) { - if (!globalThis.HAVE_GNOME) - this._input = Components.release('ydotool'); - else - this._input = Components.release('input'); - } - - if (this._dialog !== undefined) - this._dialog.destroy(); - - this.settings.disconnect(this._shareControlChangedId); - - super.destroy(); - } -}); - -export default MousepadPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/mpris.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/mpris.js deleted file mode 100755 index 2fd6a50f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/mpris.js +++ /dev/null @@ -1,917 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import Config from '../../config.js'; -import * as DBus from '../utils/dbus.js'; -import {Player} from '../components/mpris.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('MPRIS'), - description: _('Bidirectional remote media playback control'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.MPRIS', - incomingCapabilities: ['kdeconnect.mpris', 'kdeconnect.mpris.request'], - outgoingCapabilities: ['kdeconnect.mpris', 'kdeconnect.mpris.request'], - actions: {}, -}; - - -/** - * MPRIS Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/mpriscontrol - * - * See also: - * https://specifications.freedesktop.org/mpris-spec/latest/ - * https://github.com/GNOME/gnome-shell/blob/master/js/ui/mpris.js - */ -const MPRISPlugin = GObject.registerClass({ - GTypeName: 'GSConnectMPRISPlugin', -}, class MPRISPlugin extends Plugin { - - _init(device) { - super._init(device, 'mpris'); - - this._players = new Map(); - this._transferring = new WeakSet(); - this._updating = new WeakSet(); - - this._mpris = Components.acquire('mpris'); - - this._playerAddedId = this._mpris.connect( - 'player-added', - this._sendPlayerList.bind(this) - ); - - this._playerRemovedId = this._mpris.connect( - 'player-removed', - this._sendPlayerList.bind(this) - ); - - this._playerChangedId = this._mpris.connect( - 'player-changed', - this._onPlayerChanged.bind(this) - ); - - this._playerSeekedId = this._mpris.connect( - 'player-seeked', - this._onPlayerSeeked.bind(this) - ); - } - - connected() { - super.connected(); - - this._requestPlayerList(); - this._sendPlayerList(); - } - - disconnected() { - super.disconnected(); - - for (const [identity, player] of this._players) { - this._players.delete(identity); - player.destroy(); - } - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.mpris': - this._handleUpdate(packet); - break; - - case 'kdeconnect.mpris.request': - this._handleRequest(packet); - break; - } - } - - /** - * Handle a remote player update. - * - * @param {Core.Packet} packet - A `kdeconnect.mpris` - */ - _handleUpdate(packet) { - try { - if (packet.body.hasOwnProperty('playerList')) - this._handlePlayerList(packet.body.playerList); - else if (packet.body.hasOwnProperty('player')) - this._handlePlayerUpdate(packet); - } catch (e) { - debug(e, this.device.name); - } - } - - /** - * Handle an updated list of remote players. - * - * @param {string[]} playerList - A list of remote player names - */ - _handlePlayerList(playerList) { - // Destroy removed players before adding new ones - for (const player of this._players.values()) { - if (!playerList.includes(player.Identity)) { - this._players.delete(player.Identity); - player.destroy(); - } - } - - for (const identity of playerList) { - if (!this._players.has(identity)) { - const player = new PlayerRemote(this.device, identity); - this._players.set(identity, player); - } - - // Always request player updates; packets are cheap - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: identity, - requestNowPlaying: true, - requestVolume: true, - }, - }); - } - } - - /** - * Handle an update for a remote player. - * - * @param {Object} packet - A `kdeconnect.mpris` packet - */ - _handlePlayerUpdate(packet) { - const player = this._players.get(packet.body.player); - - if (player === undefined) - return; - - if (packet.body.hasOwnProperty('transferringAlbumArt')) - player.handleAlbumArt(packet); - else - player.update(packet.body); - } - - /** - * Request a list of remote players. - */ - _requestPlayerList() { - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - requestPlayerList: true, - }, - }); - } - - /** - * Handle a request for player information or action. - * - * @param {Core.Packet} packet - a `kdeconnect.mpris.request` - * @return {undefined} no return value - */ - _handleRequest(packet) { - // A request for the list of players - if (packet.body.hasOwnProperty('requestPlayerList')) - return this._sendPlayerList(); - - // A request for an unknown player; send the list of players - if (!this._mpris.hasPlayer(packet.body.player)) - return this._sendPlayerList(); - - // An album art request - if (packet.body.hasOwnProperty('albumArtUrl')) - return this._sendAlbumArt(packet); - - // A player command - this._handleCommand(packet); - } - - /** - * Handle an incoming player command or information request - * - * @param {Core.Packet} packet - A `kdeconnect.mpris.request` - */ - async _handleCommand(packet) { - if (!this.settings.get_boolean('share-players')) - return; - - let player; - - try { - player = this._mpris.getPlayer(packet.body.player); - - if (player === undefined || this._updating.has(player)) - return; - - this._updating.add(player); - - // Player Actions - if (packet.body.hasOwnProperty('action')) { - switch (packet.body.action) { - case 'PlayPause': - case 'Play': - case 'Pause': - case 'Next': - case 'Previous': - case 'Stop': - player[packet.body.action](); - break; - - default: - debug(`unknown action: ${packet.body.action}`); - } - } - - // Player Properties - if (packet.body.hasOwnProperty('setLoopStatus')) - player.LoopStatus = packet.body.setLoopStatus; - - if (packet.body.hasOwnProperty('setShuffle')) - player.Shuffle = packet.body.setShuffle; - - if (packet.body.hasOwnProperty('setVolume')) - player.Volume = packet.body.setVolume / 100; - - if (packet.body.hasOwnProperty('Seek')) - await player.Seek(packet.body.Seek); - - if (packet.body.hasOwnProperty('SetPosition')) { - // We want to avoid implementing this as a seek operation, - // because some players seek a fixed amount for every - // seek request, only respecting the sign of the parameter. - // (Chrome, for example, will only seek ±5 seconds, regardless - // what value is passed to Seek().) - const position = packet.body.SetPosition; - const metadata = player.Metadata; - if (metadata.hasOwnProperty('mpris:trackid')) { - const trackId = metadata['mpris:trackid']; - await player.SetPosition(trackId, position * 1000); - } else { - await player.Seek(position * 1000 - player.Position); - } - } - - // Information Request - let hasResponse = false; - - const response = { - type: 'kdeconnect.mpris', - body: { - player: packet.body.player, - }, - }; - - if (packet.body.hasOwnProperty('requestNowPlaying')) { - hasResponse = true; - - Object.assign(response.body, { - pos: Math.floor(player.Position / 1000), - isPlaying: (player.PlaybackStatus === 'Playing'), - canPause: player.CanPause, - canPlay: player.CanPlay, - canGoNext: player.CanGoNext, - canGoPrevious: player.CanGoPrevious, - canSeek: player.CanSeek, - loopStatus: player.LoopStatus, - shuffle: player.Shuffle, - - // default values for members that will be filled conditionally - albumArtUrl: '', - length: 0, - artist: '', - title: '', - album: '', - nowPlaying: '', - volume: 0, - }); - - const metadata = player.Metadata; - - if (metadata.hasOwnProperty('mpris:artUrl')) { - const file = Gio.File.new_for_uri(metadata['mpris:artUrl']); - response.body.albumArtUrl = file.get_uri(); - } - - if (metadata.hasOwnProperty('mpris:length')) { - const trackLen = Math.floor(metadata['mpris:length'] / 1000); - response.body.length = trackLen; - } - - if (metadata.hasOwnProperty('xesam:artist')) { - const artists = metadata['xesam:artist']; - response.body.artist = artists.join(', '); - } - - if (metadata.hasOwnProperty('xesam:title')) - response.body.title = metadata['xesam:title']; - - if (metadata.hasOwnProperty('xesam:album')) - response.body.album = metadata['xesam:album']; - - // Now Playing - if (response.body.artist && response.body.title) { - response.body.nowPlaying = [ - response.body.artist, - response.body.title, - ].join(' - '); - } else if (response.body.artist) { - response.body.nowPlaying = response.body.artist; - } else if (response.body.title) { - response.body.nowPlaying = response.body.title; - } else { - response.body.nowPlaying = _('Unknown'); - } - } - - if (packet.body.hasOwnProperty('requestVolume')) { - hasResponse = true; - response.body.volume = Math.floor(player.Volume * 100); - } - - if (hasResponse) - this.device.sendPacket(response); - } catch (e) { - debug(e, this.device.name); - } finally { - this._updating.delete(player); - } - } - - _onPlayerChanged(mpris, player) { - if (!this.settings.get_boolean('share-players')) - return; - - this._handleCommand({ - body: { - player: player.Identity, - requestNowPlaying: true, - requestVolume: true, - }, - }); - } - - _onPlayerSeeked(mpris, player, offset) { - // TODO: although we can handle full seeked signals, kdeconnect-android - // does not, and expects a position update instead - this.device.sendPacket({ - type: 'kdeconnect.mpris', - body: { - player: player.Identity, - pos: Math.floor(player.Position / 1000), - // Seek: Math.floor(offset / 1000), - }, - }); - } - - async _sendAlbumArt(packet) { - let player; - - try { - // Reject concurrent requests for album art - player = this._mpris.getPlayer(packet.body.player); - - if (player === undefined || this._transferring.has(player)) - return; - - // Ensure the requested albumArtUrl matches the current mpris:artUrl - const metadata = player.Metadata; - - if (!metadata.hasOwnProperty('mpris:artUrl')) - return; - - const file = Gio.File.new_for_uri(metadata['mpris:artUrl']); - const request = Gio.File.new_for_uri(packet.body.albumArtUrl); - - if (file.get_uri() !== request.get_uri()) - throw RangeError(`invalid URI "${packet.body.albumArtUrl}"`); - - // Transfer the album art - this._transferring.add(player); - - const transfer = this.device.createTransfer(); - - transfer.addFile({ - type: 'kdeconnect.mpris', - body: { - transferringAlbumArt: true, - player: packet.body.player, - albumArtUrl: packet.body.albumArtUrl, - }, - }, file); - - await transfer.start(); - } catch (e) { - debug(e, this.device.name); - } finally { - this._transferring.delete(player); - } - } - - /** - * Send the list of player identities and indicate whether we support - * transferring album art - */ - _sendPlayerList() { - let playerList = []; - - if (this.settings.get_boolean('share-players')) - playerList = this._mpris.getIdentities(); - - this.device.sendPacket({ - type: 'kdeconnect.mpris', - body: { - playerList: playerList, - supportAlbumArtPayload: true, - }, - }); - } - - destroy() { - if (this._mpris !== undefined) { - this._mpris.disconnect(this._playerAddedId); - this._mpris.disconnect(this._playerRemovedId); - this._mpris.disconnect(this._playerChangedId); - this._mpris.disconnect(this._playerSeekedId); - this._mpris = Components.release('mpris'); - } - - for (const [identity, player] of this._players) { - this._players.delete(identity); - player.destroy(); - } - - super.destroy(); - } -}); - - -/* - * A class for mirroring a remote Media Player on DBus - */ -const PlayerRemote = GObject.registerClass({ - GTypeName: 'GSConnectMPRISPlayerRemote', -}, class PlayerRemote extends Player { - - _init(device, identity) { - super._init(); - - this._device = device; - this._Identity = identity; - this._isPlaying = false; - - this._artist = null; - this._title = null; - this._album = null; - this._length = 0; - this._artUrl = null; - - this._ownerId = 0; - this._connection = null; - this._applicationIface = null; - this._playerIface = null; - } - - _getFile(albumArtUrl) { - const hash = GLib.compute_checksum_for_string(GLib.ChecksumType.MD5, - albumArtUrl, -1); - const path = GLib.build_filenamev([Config.CACHEDIR, hash]); - - return Gio.File.new_for_uri(`file://${path}`); - } - - _requestAlbumArt(state) { - if (this._artUrl === state.albumArtUrl) - return; - - const file = this._getFile(state.albumArtUrl); - - if (file.query_exists(null)) { - this._artUrl = file.get_uri(); - this._Metadata = undefined; - this.notify('Metadata'); - } else { - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - albumArtUrl: state.albumArtUrl, - }, - }); - } - } - - _updateMetadata(state) { - let metadataChanged = false; - - if (state.hasOwnProperty('artist')) { - if (this._artist !== state.artist) { - this._artist = state.artist; - metadataChanged = true; - } - } else if (this._artist) { - this._artist = null; - metadataChanged = true; - } - - if (state.hasOwnProperty('title')) { - if (this._title !== state.title) { - this._title = state.title; - metadataChanged = true; - } - } else if (this._title) { - this._title = null; - metadataChanged = true; - } - - if (state.hasOwnProperty('album')) { - if (this._album !== state.album) { - this._album = state.album; - metadataChanged = true; - } - } else if (this._album) { - this._album = null; - metadataChanged = true; - } - - if (state.hasOwnProperty('length')) { - if (this._length !== state.length * 1000) { - this._length = state.length * 1000; - metadataChanged = true; - } - } else if (this._length) { - this._length = 0; - metadataChanged = true; - } - - if (state.hasOwnProperty('albumArtUrl')) { - this._requestAlbumArt(state); - } else if (this._artUrl) { - this._artUrl = null; - metadataChanged = true; - } - - if (metadataChanged) { - this._Metadata = undefined; - this.notify('Metadata'); - } - } - - async export() { - try { - if (this._connection === null) { - this._connection = await DBus.newConnection(); - const MPRISIface = Config.DBUS.lookup_interface('org.mpris.MediaPlayer2'); - const MPRISPlayerIface = Config.DBUS.lookup_interface('org.mpris.MediaPlayer2.Player'); - - if (this._applicationIface === null) { - this._applicationIface = new DBus.Interface({ - g_instance: this, - g_connection: this._connection, - g_object_path: '/org/mpris/MediaPlayer2', - g_interface_info: MPRISIface, - }); - } - - if (this._playerIface === null) { - this._playerIface = new DBus.Interface({ - g_instance: this, - g_connection: this._connection, - g_object_path: '/org/mpris/MediaPlayer2', - g_interface_info: MPRISPlayerIface, - }); - } - } - - if (this._ownerId !== 0) - return; - - const name = [ - this.device.name, - this.Identity, - ].join('').replace(/[\W]*/g, ''); - - this._ownerId = Gio.bus_own_name_on_connection( - this._connection, - `org.mpris.MediaPlayer2.GSConnect.${name}`, - Gio.BusNameOwnerFlags.NONE, - null, - null - ); - } catch (e) { - debug(e, this.Identity); - } - } - - unexport() { - if (this._ownerId === 0) - return; - - Gio.bus_unown_name(this._ownerId); - this._ownerId = 0; - } - - /** - * Download album art for the current track of the remote player. - * - * @param {Core.Packet} packet - A `kdeconnect.mpris` packet - */ - async handleAlbumArt(packet) { - let file; - - try { - file = this._getFile(packet.body.albumArtUrl); - - // Transfer the album art - const transfer = this.device.createTransfer(); - transfer.addFile(packet, file); - - await transfer.start(); - - this._artUrl = file.get_uri(); - this._Metadata = undefined; - this.notify('Metadata'); - } catch (e) { - debug(e, this.device.name); - - if (file) - file.delete_async(GLib.PRIORITY_DEFAULT, null, null); - } - } - - /** - * Update the internal state of the media player. - * - * @param {Core.Packet} state - The body of a `kdeconnect.mpris` packet - */ - update(state) { - this.freeze_notify(); - - // Metadata - if (state.hasOwnProperty('nowPlaying') || - state.hasOwnProperty('artist') || - state.hasOwnProperty('title')) - this._updateMetadata(state); - - // Playback Status - if (state.hasOwnProperty('isPlaying')) { - if (this._isPlaying !== state.isPlaying) { - this._isPlaying = state.isPlaying; - this.notify('PlaybackStatus'); - } - } - - if (state.hasOwnProperty('canPlay')) { - if (this.CanPlay !== state.canPlay) { - this._CanPlay = state.canPlay; - this.notify('CanPlay'); - } - } - - if (state.hasOwnProperty('canPause')) { - if (this.CanPause !== state.canPause) { - this._CanPause = state.canPause; - this.notify('CanPause'); - } - } - - if (state.hasOwnProperty('canGoNext')) { - if (this.CanGoNext !== state.canGoNext) { - this._CanGoNext = state.canGoNext; - this.notify('CanGoNext'); - } - } - - if (state.hasOwnProperty('canGoPrevious')) { - if (this.CanGoPrevious !== state.canGoPrevious) { - this._CanGoPrevious = state.canGoPrevious; - this.notify('CanGoPrevious'); - } - } - - if (state.hasOwnProperty('pos')) - this._Position = state.pos * 1000; - - if (state.hasOwnProperty('volume')) { - if (this.Volume !== state.volume / 100) { - this._Volume = state.volume / 100; - this.notify('Volume'); - } - } - - this.thaw_notify(); - - if (!this._isPlaying && !this.CanControl) - this.unexport(); - else - this.export(); - } - - /* - * Native properties - */ - get device() { - return this._device; - } - - /* - * The org.mpris.MediaPlayer2.Player Interface - */ - get CanControl() { - return (this.CanPlay || this.CanPause); - } - - get Metadata() { - if (this._Metadata === undefined) { - this._Metadata = {}; - - if (this._artist) { - this._Metadata['xesam:artist'] = new GLib.Variant('as', - [this._artist]); - } - - if (this._title) { - this._Metadata['xesam:title'] = new GLib.Variant('s', - this._title); - } - - if (this._album) { - this._Metadata['xesam:album'] = new GLib.Variant('s', - this._album); - } - - if (this._artUrl) { - this._Metadata['mpris:artUrl'] = new GLib.Variant('s', - this._artUrl); - } - - this._Metadata['mpris:length'] = new GLib.Variant('x', - this._length); - } - - return this._Metadata; - } - - get PlaybackStatus() { - if (this._isPlaying) - return 'Playing'; - - return 'Stopped'; - } - - get Volume() { - if (this._Volume === undefined) - this._Volume = 0.3; - - return this._Volume; - } - - set Volume(level) { - if (this._Volume === level) - return; - - this._Volume = level; - this.notify('Volume'); - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - setVolume: Math.floor(this._Volume * 100), - }, - }); - } - - Next() { - if (!this.CanGoNext) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - action: 'Next', - }, - }); - } - - Pause() { - if (!this.CanPause) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - action: 'Pause', - }, - }); - } - - Play() { - if (!this.CanPlay) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - action: 'Play', - }, - }); - } - - PlayPause() { - if (!this.CanPlay && !this.CanPause) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - action: 'PlayPause', - }, - }); - } - - Previous() { - if (!this.CanGoPrevious) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - action: 'Previous', - }, - }); - } - - Seek(offset) { - if (!this.CanSeek) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - Seek: offset, - }, - }); - } - - SetPosition(trackId, position) { - debug(`${this._Identity}: SetPosition(${trackId}, ${position})`); - - if (!this.CanControl || !this.CanSeek) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - SetPosition: position / 1000, - }, - }); - } - - Stop() { - if (!this.CanControl) - return; - - this.device.sendPacket({ - type: 'kdeconnect.mpris.request', - body: { - player: this.Identity, - action: 'Stop', - }, - }); - } - - destroy() { - this.unexport(); - - if (this._connection) { - this._connection.close(null, null); - this._connection = null; - - if (this._applicationIface) { - this._applicationIface.destroy(); - this._applicationIface = null; - } - - if (this._playerIface) { - this._playerIface.destroy(); - this._playerIface = null; - } - } - } -}); - -export default MPRISPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/notification.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/notification.js deleted file mode 100755 index bb317db6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/notification.js +++ /dev/null @@ -1,694 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import * as Components from '../components/index.js'; -import Config from '../../config.js'; -import Plugin from '../plugin.js'; -import ReplyDialog from '../ui/notification.js'; - - -export const Metadata = { - label: _('Notifications'), - description: _('Share notifications with the paired device'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Notification', - incomingCapabilities: [ - 'kdeconnect.notification', - 'kdeconnect.notification.request', - ], - outgoingCapabilities: [ - 'kdeconnect.notification', - 'kdeconnect.notification.action', - 'kdeconnect.notification.reply', - 'kdeconnect.notification.request', - ], - actions: { - withdrawNotification: { - label: _('Cancel Notification'), - icon_name: 'preferences-system-notifications-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.notification'], - }, - closeNotification: { - label: _('Close Notification'), - icon_name: 'preferences-system-notifications-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.notification.request'], - }, - replyNotification: { - label: _('Reply Notification'), - icon_name: 'preferences-system-notifications-symbolic', - - parameter_type: new GLib.VariantType('(ssa{ss})'), - incoming: ['kdeconnect.notification'], - outgoing: ['kdeconnect.notification.reply'], - }, - sendNotification: { - label: _('Send Notification'), - icon_name: 'preferences-system-notifications-symbolic', - - parameter_type: new GLib.VariantType('a{sv}'), - incoming: [], - outgoing: ['kdeconnect.notification'], - }, - activateNotification: { - label: _('Activate Notification'), - icon_name: 'preferences-system-notifications-symbolic', - - parameter_type: new GLib.VariantType('(ss)'), - incoming: [], - outgoing: ['kdeconnect.notification.action'], - }, - }, -}; - - -// A regex for our custom notificaiton ids -const ID_REGEX = /^(fdo|gtk)\|([^|]+)\|(.*)$/; - -// A list of known SMS apps -const SMS_APPS = [ - // Popular apps that don't contain the string 'sms' - 'com.android.messaging', // AOSP - 'com.google.android.apps.messaging', // Google Messages - 'com.textra', // Textra - 'xyz.klinker.messenger', // Pulse - 'com.calea.echo', // Mood Messenger - 'com.moez.QKSMS', // QKSMS - 'rpkandrodev.yaata', // YAATA - 'com.tencent.mm', // WeChat - 'com.viber.voip', // Viber - 'com.kakao.talk', // KakaoTalk - 'com.concentriclivers.mms.com.android.mms', // AOSP Clone - 'fr.slvn.mms', // AOSP Clone - 'com.promessage.message', // - 'com.htc.sense.mms', // HTC Messages - - // Known not to work with sms plugin - 'org.thoughtcrime.securesms', // Signal Private Messenger - 'com.samsung.android.messaging', // Samsung Messages -]; - - -/** - * Try to determine if an notification is from an SMS app - * - * @param {Core.Packet} packet - A `kdeconnect.notification` - * @return {boolean} Whether the notification is from an SMS app - */ -function _isSmsNotification(packet) { - const id = packet.body.id; - - if (id.includes('sms')) - return true; - - for (let i = 0, len = SMS_APPS.length; i < len; i++) { - if (id.includes(SMS_APPS[i])) - return true; - } - - return false; -} - - -/** - * Remove a local libnotify or Gtk notification. - * - * @param {String|Number} id - Gtk (string) or libnotify id (uint32) - * @param {String|null} application - Application Id if Gtk or null - */ -function _removeNotification(id, application = null) { - let name, path, method, variant; - - if (application !== null) { - name = 'org.gtk.Notifications'; - method = 'RemoveNotification'; - path = '/org/gtk/Notifications'; - variant = new GLib.Variant('(ss)', [application, id]); - } else { - name = 'org.freedesktop.Notifications'; - path = '/org/freedesktop/Notifications'; - method = 'CloseNotification'; - variant = new GLib.Variant('(u)', [id]); - } - - Gio.DBus.session.call( - name, path, name, method, variant, null, - Gio.DBusCallFlags.NONE, -1, null, - (connection, res) => { - try { - connection.call_finish(res); - } catch (e) { - logError(e); - } - } - ); -} - - -/** - * Notification Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/notifications - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sendnotifications - */ -const NotificationPlugin = GObject.registerClass({ - GTypeName: 'GSConnectNotificationPlugin', -}, class NotificationPlugin extends Plugin { - - _init(device) { - super._init(device, 'notification'); - - this._listener = Components.acquire('notification'); - this._session = Components.acquire('session'); - - this._notificationAddedId = this._listener.connect( - 'notification-added', - this._onNotificationAdded.bind(this) - ); - - // Load application notification settings - this._applicationsChangedId = this.settings.connect( - 'changed::applications', - this._onApplicationsChanged.bind(this) - ); - this._onApplicationsChanged(this.settings, 'applications'); - this._applicationsChangedSkip = false; - } - - connected() { - super.connected(); - - this._requestNotifications(); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.notification': - this._handleNotification(packet); - break; - - // TODO - case 'kdeconnect.notification.action': - this._handleNotificationAction(packet); - break; - - // No Linux/BSD desktop notifications are repliable as yet - case 'kdeconnect.notification.reply': - debug(`Not implemented: ${packet.type}`); - break; - - case 'kdeconnect.notification.request': - this._handleNotificationRequest(packet); - break; - - default: - debug(`Unknown notification packet: ${packet.type}`); - } - } - - _onApplicationsChanged(settings, key) { - if (this._applicationsChangedSkip) - return; - - try { - const json = settings.get_string(key); - this._applications = JSON.parse(json); - } catch (e) { - debug(e, this.device.name); - - this._applicationsChangedSkip = true; - settings.set_string(key, '{}'); - this._applicationsChangedSkip = false; - } - } - - _onNotificationAdded(listener, notification) { - try { - const notif = notification.full_unpack(); - - // An unconfigured application - if (notif.appName && !this._applications[notif.appName]) { - this._applications[notif.appName] = { - iconName: 'system-run-symbolic', - enabled: true, - }; - - // Store the themed icons for the device preferences window - if (notif.icon === undefined) { - // Keep default - - } else if (typeof notif.icon === 'string') { - this._applications[notif.appName].iconName = notif.icon; - - } else if (notif.icon instanceof Gio.ThemedIcon) { - const iconName = notif.icon.get_names()[0]; - this._applications[notif.appName].iconName = iconName; - } - - this._applicationsChangedSkip = true; - this.settings.set_string( - 'applications', - JSON.stringify(this._applications) - ); - this._applicationsChangedSkip = false; - } - - // Sending notifications forbidden - if (!this.settings.get_boolean('send-notifications')) - return; - - // Sending when the session is active is forbidden - if (!this.settings.get_boolean('send-active') && this._session.active) - return; - - // Notifications disabled for this application - if (notif.appName && !this._applications[notif.appName].enabled) - return; - - this.sendNotification(notif); - } catch (e) { - debug(e, this.device.name); - } - } - - /** - * Handle an incoming notification or closed report. - * - * FIXME: upstream kdeconnect-android is tagging many notifications as - * `silent`, causing them to never be shown. Since we already handle - * duplicates in the Shell, we ignore that flag for now. - * - * @param {Core.Packet} packet - A `kdeconnect.notification` - */ - _handleNotification(packet) { - // A report that a remote notification has been dismissed - if (packet.body.hasOwnProperty('isCancel')) - this.device.hideNotification(packet.body.id); - - // A normal, remote notification - else - this._receiveNotification(packet); - } - - /** - * Handle an incoming request to activate a notification action. - * - * @param {Core.Packet} packet - A `kdeconnect.notification.action` - */ - _handleNotificationAction(packet) { - throw new GObject.NotImplementedError(); - } - - /** - * Handle an incoming request to close or list notifications. - * - * @param {Core.Packet} packet - A `kdeconnect.notification.request` - */ - _handleNotificationRequest(packet) { - // A request for our notifications. This isn't implemented and would be - // pretty hard to without communicating with GNOME Shell. - if (packet.body.hasOwnProperty('request')) - return; - - // A request to close a local notification - // - // TODO: kdeconnect-android doesn't send these, and will instead send a - // kdeconnect.notification packet with isCancel and an id of "0". - // - // For clients that do support it, we report notification ids in the - // form "type|application-id|notification-id" so we can close it with - // the appropriate service. - if (packet.body.hasOwnProperty('cancel')) { - const [, type, application, id] = ID_REGEX.exec(packet.body.cancel); - - if (type === 'fdo') - _removeNotification(parseInt(id)); - else if (type === 'gtk') - _removeNotification(id, application); - } - } - - /** - * Upload an icon from a GLib.Bytes object. - * - * @param {Core.Packet} packet - The packet for the notification - * @param {GLib.Bytes} bytes - The icon bytes - */ - _uploadBytesIcon(packet, bytes) { - const stream = Gio.MemoryInputStream.new_from_bytes(bytes); - this._uploadIconStream(packet, stream, bytes.get_size()); - } - - /** - * Upload an icon from a Gio.File object. - * - * @param {Core.Packet} packet - A `kdeconnect.notification` - * @param {Gio.File} file - A file object for the icon - */ - async _uploadFileIcon(packet, file) { - const read = file.read_async(GLib.PRIORITY_DEFAULT, null); - const query = file.query_info_async('standard::size', - Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_DEFAULT, null); - const [stream, info] = await Promise.all([read, query]); - - this._uploadIconStream(packet, stream, info.get_size()); - } - - /** - * A function for uploading GThemedIcons - * - * @param {Core.Packet} packet - The packet for the notification - * @param {Gio.ThemedIcon} icon - The GIcon to upload - */ - _uploadThemedIcon(packet, icon) { - const theme = Gtk.IconTheme.get_default(); - let file = null; - - for (const name of icon.names) { - // NOTE: kdeconnect-android doesn't support SVGs - const size = Math.max.apply(null, theme.get_icon_sizes(name)); - const info = theme.lookup_icon(name, size, Gtk.IconLookupFlags.NO_SVG); - - // Send the first icon we find from the options - if (info) { - file = Gio.File.new_for_path(info.get_filename()); - break; - } - } - - if (file) - this._uploadFileIcon(packet, file); - else - this.device.sendPacket(packet); - } - - /** - * All icon types end up being uploaded in this function. - * - * @param {Core.Packet} packet - The packet for the notification - * @param {Gio.InputStream} stream - A stream to read the icon bytes from - * @param {number} size - Size of the icon in bytes - */ - async _uploadIconStream(packet, stream, size) { - try { - const transfer = this.device.createTransfer(); - transfer.addStream(packet, stream, size); - - await transfer.start(); - } catch (e) { - debug(e); - - this.device.sendPacket(packet); - } - } - - /** - * Upload an icon from a GIcon or themed icon name. - * - * @param {Core.Packet} packet - A `kdeconnect.notification` - * @param {Gio.Icon|string|null} icon - An icon or %null - * @return {Promise} A promise for the operation - */ - _uploadIcon(packet, icon = null) { - // Normalize strings into GIcons - if (typeof icon === 'string') - icon = Gio.Icon.new_for_string(icon); - - if (icon instanceof Gio.ThemedIcon) - return this._uploadThemedIcon(packet, icon); - - if (icon instanceof Gio.FileIcon) - return this._uploadFileIcon(packet, icon.get_file()); - - if (icon instanceof Gio.BytesIcon) - return this._uploadBytesIcon(packet, icon.get_bytes()); - - return this.device.sendPacket(packet); - } - - /** - * Send a local notification to the remote device. - * - * @param {Object} notif - A dictionary of notification parameters - * @param {string} notif.appName - The notifying application - * @param {string} notif.id - The notification ID - * @param {string} notif.title - The notification title - * @param {string} notif.body - The notification body - * @param {string} notif.ticker - The notification title & body - * @param {boolean} notif.isClearable - If the notification can be closed - * @param {string|Gio.Icon} notif.icon - An icon name or GIcon - */ - async sendNotification(notif) { - try { - const icon = notif.icon || null; - delete notif.icon; - - await this._uploadIcon({ - type: 'kdeconnect.notification', - body: notif, - }, icon); - } catch (e) { - logError(e); - } - } - - async _downloadIcon(packet) { - try { - if (!packet.hasPayload()) - return null; - - // Save the file in the global cache - const path = GLib.build_filenamev([ - Config.CACHEDIR, - packet.body.payloadHash || `${Date.now()}`, - ]); - - // Check if we've already downloaded this icon - // NOTE: if we reject the transfer kdeconnect-android will resend - // the notification packet, which may cause problems wrt #789 - const file = Gio.File.new_for_path(path); - - if (file.query_exists(null)) - return new Gio.FileIcon({file: file}); - - // Open the target path and create a transfer - const transfer = this.device.createTransfer(); - - transfer.addFile(packet, file); - - try { - await transfer.start(); - - return new Gio.FileIcon({file: file}); - } catch (e) { - debug(e, this.device.name); - - file.delete_async(GLib.PRIORITY_DEFAULT, null, null); - return null; - } - } catch (e) { - debug(e, this.device.name); - return null; - } - } - - /** - * Receive an incoming notification. - * - * @param {Core.Packet} packet - A `kdeconnect.notification` - */ - async _receiveNotification(packet) { - try { - // Set defaults - let action = null; - let buttons = []; - let id = packet.body.id; - let title = packet.body.appName; - let body = `${packet.body.title}: ${packet.body.text}`; - let icon = await this._downloadIcon(packet); - - // Repliable Notification - if (packet.body.requestReplyId) { - id = `${packet.body.id}|${packet.body.requestReplyId}`; - action = { - name: 'replyNotification', - parameter: new GLib.Variant('(ssa{ss})', [ - packet.body.requestReplyId, - '', - { - appName: packet.body.appName, - title: packet.body.title, - text: packet.body.text, - }, - ]), - }; - } - - // Notification Actions - if (packet.body.actions) { - buttons = packet.body.actions.map(action => { - return { - label: action, - action: 'activateNotification', - parameter: new GLib.Variant('(ss)', [id, action]), - }; - }); - } - - // Special case for Missed Calls - if (packet.body.id.includes('MissedCall')) { - title = packet.body.title; - body = packet.body.text; - - if (icon === null) - icon = new Gio.ThemedIcon({name: 'call-missed-symbolic'}); - - // Special case for SMS notifications - } else if (_isSmsNotification(packet)) { - title = packet.body.title; - body = packet.body.text; - action = { - name: 'replySms', - parameter: new GLib.Variant('s', packet.body.title), - }; - - if (icon === null) - icon = new Gio.ThemedIcon({name: 'sms-symbolic'}); - - // Special case where 'appName' is the same as 'title' - } else if (packet.body.appName === packet.body.title) { - body = packet.body.text; - } - - // Use the device icon if we still don't have one - if (icon === null) - icon = new Gio.ThemedIcon({name: this.device.icon_name}); - - // Show the notification - this.device.showNotification({ - id: id, - title: title, - body: body, - icon: icon, - action: action, - buttons: buttons, - }); - } catch (e) { - logError(e); - } - } - - /** - * Request the remote notifications be sent - */ - _requestNotifications() { - this.device.sendPacket({ - type: 'kdeconnect.notification.request', - body: {request: true}, - }); - } - - /** - * Report that a local notification has been closed/dismissed. - * TODO: kdeconnect-android doesn't handle incoming isCancel packets. - * - * @param {string} id - The local notification id - */ - withdrawNotification(id) { - this.device.sendPacket({ - type: 'kdeconnect.notification', - body: { - isCancel: true, - id: id, - }, - }); - } - - /** - * Close a remote notification. - * TODO: ignore local notifications - * - * @param {string} id - The remote notification id - */ - closeNotification(id) { - this.device.sendPacket({ - type: 'kdeconnect.notification.request', - body: {cancel: id}, - }); - } - - /** - * Reply to a notification sent with a requestReplyId UUID - * - * @param {string} uuid - The requestReplyId for the repliable notification - * @param {string} message - The message to reply with - * @param {Object} notification - The original notification packet - */ - replyNotification(uuid, message, notification) { - // If this happens for some reason, things will explode - if (!uuid) - throw Error('Missing UUID'); - - // If the message has no content, open a dialog for the user to add one - if (!message) { - const dialog = new ReplyDialog({ - device: this.device, - uuid: uuid, - notification: notification, - plugin: this, - }); - dialog.present(); - - // Otherwise just send the reply - } else { - this.device.sendPacket({ - type: 'kdeconnect.notification.reply', - body: { - requestReplyId: uuid, - message: message, - }, - }); - } - } - - /** - * Activate a remote notification action - * - * @param {string} id - The remote notification id - * @param {string} action - The notification action (label) - */ - activateNotification(id, action) { - this.device.sendPacket({ - type: 'kdeconnect.notification.action', - body: { - action: action, - key: id, - }, - }); - } - - destroy() { - this.settings.disconnect(this._applicationsChangedId); - - if (this._listener !== undefined) { - this._listener.disconnect(this._notificationAddedId); - this._listener = Components.release('notification'); - } - - if (this._session !== undefined) - this._session = Components.release('session'); - - super.destroy(); - } -}); - -export default NotificationPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/ping.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/ping.js deleted file mode 100755 index 011ecf02..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/ping.js +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Ping'), - description: _('Send and receive pings'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Ping', - incomingCapabilities: ['kdeconnect.ping'], - outgoingCapabilities: ['kdeconnect.ping'], - actions: { - ping: { - label: _('Ping'), - icon_name: 'dialog-information-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.ping'], - }, - }, -}; - - -/** - * Ping Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/ping - */ -const PingPlugin = GObject.registerClass({ - GTypeName: 'GSConnectPingPlugin', -}, class PingPlugin extends Plugin { - - _init(device) { - super._init(device, 'ping'); - } - - handlePacket(packet) { - // Notification - const notif = { - title: this.device.name, - body: _('Ping'), - icon: new Gio.ThemedIcon({name: `${this.device.icon_name}`}), - }; - - if (packet.body.message) { - // TRANSLATORS: An optional message accompanying a ping, rarely if ever used - // eg. Ping: A message sent with ping - notif.body = _('Ping: %s').format(packet.body.message); - } - - this.device.showNotification(notif); - } - - ping(message = '') { - const packet = { - type: 'kdeconnect.ping', - body: {}, - }; - - if (message.length) - packet.body.message = message; - - this.device.sendPacket(packet); - } -}); - -export default PingPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/presenter.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/presenter.js deleted file mode 100755 index 3cccab03..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/presenter.js +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Presentation'), - description: _('Use the paired device as a presenter'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Presenter', - incomingCapabilities: ['kdeconnect.presenter'], - outgoingCapabilities: [], - actions: {}, -}; - - -/** - * Presenter Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/presenter - * https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/PresenterPlugin/ - */ -const PresenterPlugin = GObject.registerClass({ - GTypeName: 'GSConnectPresenterPlugin', -}, class PresenterPlugin extends Plugin { - - _init(device) { - super._init(device, 'presenter'); - - if (!globalThis.HAVE_GNOME) - this._input = Components.acquire('ydotool'); - else - this._input = Components.acquire('input'); - } - - handlePacket(packet) { - if (packet.body.hasOwnProperty('dx')) { - this._input.movePointer( - packet.body.dx * 1000, - packet.body.dy * 1000 - ); - } else if (packet.body.stop) { - // Currently unsupported and unnecessary as we just re-use the mouse - // pointer instead of showing an arbitrary window. - } - } - - destroy() { - if (this._input !== undefined) { - if (!globalThis.HAVE_GNOME) - this._input = Components.release('ydotool'); - else - this._input = Components.release('input'); - } - - super.destroy(); - } -}); - -export default PresenterPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/runcommand.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/runcommand.js deleted file mode 100755 index c57c6c0f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/runcommand.js +++ /dev/null @@ -1,254 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Run Commands'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.RunCommand', - description: _('Run commands on your paired device or let the device run predefined commands on this PC'), - incomingCapabilities: [ - 'kdeconnect.runcommand', - 'kdeconnect.runcommand.request', - ], - outgoingCapabilities: [ - 'kdeconnect.runcommand', - 'kdeconnect.runcommand.request', - ], - actions: { - commands: { - label: _('Commands'), - icon_name: 'system-run-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: ['kdeconnect.runcommand'], - outgoing: ['kdeconnect.runcommand.request'], - }, - executeCommand: { - label: _('Commands'), - icon_name: 'system-run-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: ['kdeconnect.runcommand'], - outgoing: ['kdeconnect.runcommand.request'], - }, - }, -}; - - -/** - * RunCommand Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/remotecommands - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/runcommand - */ -const RunCommandPlugin = GObject.registerClass({ - GTypeName: 'GSConnectRunCommandPlugin', - Properties: { - 'remote-commands': GObject.param_spec_variant( - 'remote-commands', - 'Remote Command List', - 'A list of the device\'s remote commands', - new GLib.VariantType('a{sv}'), - null, - GObject.ParamFlags.READABLE - ), - }, -}, class RunCommandPlugin extends Plugin { - - _init(device) { - super._init(device, 'runcommand'); - - // Local Commands - this._commandListChangedId = this.settings.connect( - 'changed::command-list', - this._sendCommandList.bind(this) - ); - - // We cache remote commands so they can be used in the settings even - // when the device is offline. - this._remote_commands = {}; - this.cacheProperties(['_remote_commands']); - } - - get remote_commands() { - return this._remote_commands; - } - - connected() { - super.connected(); - - this._sendCommandList(); - this._requestCommandList(); - this._handleCommandList(this.remote_commands); - } - - clearCache() { - this._remote_commands = {}; - this.notify('remote-commands'); - } - - cacheLoaded() { - if (!this.device.connected) - return; - - this._sendCommandList(); - this._requestCommandList(); - this._handleCommandList(this.remote_commands); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.runcommand': - this._handleCommandList(packet.body.commandList); - break; - - case 'kdeconnect.runcommand.request': - if (packet.body.hasOwnProperty('key')) - this._handleCommand(packet.body.key); - - else if (packet.body.hasOwnProperty('requestCommandList')) - this._sendCommandList(); - - break; - } - } - - /** - * Handle a request to execute the local command with the UUID @key - * - * @param {string} key - The UUID of the local command - */ - _handleCommand(key) { - try { - const commands = this.settings.get_value('command-list'); - const commandList = commands.recursiveUnpack(); - - if (!commandList.hasOwnProperty(key)) { - throw new Gio.IOErrorEnum({ - code: Gio.IOErrorEnum.PERMISSION_DENIED, - message: `Unknown command: ${key}`, - }); - } - - this.device.launchProcess([ - '/bin/sh', - '-c', - commandList[key].command, - ]); - } catch (e) { - logError(e, this.device.name); - } - } - - /** - * Parse the response to a request for the remote command list. Remove the - * command menu if there are no commands, otherwise amend the menu. - * - * @param {string|Object[]} commandList - A list of remote commands - */ - _handleCommandList(commandList) { - // See: https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/1051 - if (typeof commandList === 'string') { - try { - commandList = JSON.parse(commandList); - } catch (e) { - commandList = {}; - } - } - - this._remote_commands = commandList; - this.notify('remote-commands'); - - const commandEntries = Object.entries(this.remote_commands); - - // If there are no commands, hide the menu by disabling the action - this.device.lookup_action('commands').enabled = (commandEntries.length > 0); - - // Commands Submenu - const submenu = new Gio.Menu(); - - for (const [uuid, info] of commandEntries) { - const item = new Gio.MenuItem(); - item.set_label(info.name); - item.set_icon( - new Gio.ThemedIcon({name: 'application-x-executable-symbolic'}) - ); - item.set_detailed_action(`device.executeCommand::${uuid}`); - submenu.append_item(item); - } - - // Commands Item - const item = new Gio.MenuItem(); - item.set_detailed_action('device.commands::menu'); - item.set_attribute_value( - 'hidden-when', - new GLib.Variant('s', 'action-disabled') - ); - item.set_icon(new Gio.ThemedIcon({name: 'system-run-symbolic'})); - item.set_label(_('Commands')); - item.set_submenu(submenu); - - // If the submenu item is already present it will be replaced - const menuActions = this.device.settings.get_strv('menu-actions'); - const index = menuActions.indexOf('commands'); - - if (index > -1) { - this.device.removeMenuAction('device.commands'); - this.device.addMenuItem(item, index); - } - } - - /** - * Send a request for the remote command list - */ - _requestCommandList() { - this.device.sendPacket({ - type: 'kdeconnect.runcommand.request', - body: {requestCommandList: true}, - }); - } - - /** - * Send the local command list - */ - _sendCommandList() { - const commands = this.settings.get_value('command-list').recursiveUnpack(); - const commandList = JSON.stringify(commands); - - this.device.sendPacket({ - type: 'kdeconnect.runcommand', - body: {commandList: commandList}, - }); - } - - /** - * Placeholder function for command action - */ - commands() {} - - /** - * Send a request to execute the remote command with the UUID @key - * - * @param {string} key - The UUID of the remote command - */ - executeCommand(key) { - this.device.sendPacket({ - type: 'kdeconnect.runcommand.request', - body: {key: key}, - }); - } - - destroy() { - this.settings.disconnect(this._commandListChangedId); - - super.destroy(); - } -}); - -export default RunCommandPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/sftp.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/sftp.js deleted file mode 100755 index 2789ff36..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/sftp.js +++ /dev/null @@ -1,487 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Config from '../../config.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('SFTP'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SFTP', - description: _('Browse the paired device filesystem'), - incomingCapabilities: ['kdeconnect.sftp'], - outgoingCapabilities: ['kdeconnect.sftp.request'], - actions: { - mount: { - label: _('Mount'), - icon_name: 'folder-remote-symbolic', - - parameter_type: null, - incoming: ['kdeconnect.sftp'], - outgoing: ['kdeconnect.sftp.request'], - }, - unmount: { - label: _('Unmount'), - icon_name: 'media-eject-symbolic', - - parameter_type: null, - incoming: ['kdeconnect.sftp'], - outgoing: ['kdeconnect.sftp.request'], - }, - }, -}; - - -const MAX_MOUNT_DIRS = 12; - - -/** - * SFTP Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sftp - * https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SftpPlugin - */ -const SFTPPlugin = GObject.registerClass({ - GTypeName: 'GSConnectSFTPPlugin', -}, class SFTPPlugin extends Plugin { - - _init(device) { - super._init(device, 'sftp'); - - this._gmount = null; - this._mounting = false; - - // A reusable launcher for ssh processes - this._launcher = new Gio.SubprocessLauncher({ - flags: (Gio.SubprocessFlags.STDOUT_PIPE | - Gio.SubprocessFlags.STDERR_MERGE), - }); - - // Watch the volume monitor - this._volumeMonitor = Gio.VolumeMonitor.get(); - - this._mountAddedId = this._volumeMonitor.connect( - 'mount-added', - this._onMountAdded.bind(this) - ); - - this._mountRemovedId = this._volumeMonitor.connect( - 'mount-removed', - this._onMountRemoved.bind(this) - ); - } - - get gmount() { - if (this._gmount === null && this.device.connected) { - const host = this.device.channel.host; - - const regex = new RegExp( - `sftp://(${host}):(1739|17[4-5][0-9]|176[0-4])` - ); - - for (const mount of this._volumeMonitor.get_mounts()) { - const uri = mount.get_root().get_uri(); - - if (regex.test(uri)) { - this._gmount = mount; - this._addSubmenu(mount); - this._addSymlink(mount); - - break; - } - } - } - - return this._gmount; - } - - connected() { - super.connected(); - - // Only enable for Lan connections - if (this.device.channel.constructor.name === 'LanChannel') { // FIXME: Circular import workaround - if (this.settings.get_boolean('automount')) - this.mount(); - } else { - this.device.lookup_action('mount').enabled = false; - this.device.lookup_action('unmount').enabled = false; - } - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.sftp': - if (packet.body.hasOwnProperty('errorMessage')) - this._handleError(packet); - else - this._handleMount(packet); - - break; - } - } - - _onMountAdded(monitor, mount) { - if (this._gmount !== null || !this.device.connected) - return; - - const host = this.device.channel.host; - const regex = new RegExp(`sftp://(${host}):(1739|17[4-5][0-9]|176[0-4])`); - const uri = mount.get_root().get_uri(); - - if (!regex.test(uri)) - return; - - this._gmount = mount; - this._addSubmenu(mount); - this._addSymlink(mount); - } - - _onMountRemoved(monitor, mount) { - if (this.gmount !== mount) - return; - - this._gmount = null; - this._removeSubmenu(); - } - - async _listDirectories(mount) { - const file = mount.get_root(); - - const iter = await file.enumerate_children_async( - Gio.FILE_ATTRIBUTE_STANDARD_NAME, - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - GLib.PRIORITY_DEFAULT, - this.cancellable); - - const infos = await iter.next_files_async(MAX_MOUNT_DIRS, - GLib.PRIORITY_DEFAULT, this.cancellable); - iter.close_async(GLib.PRIORITY_DEFAULT, null, null); - - const directories = {}; - - for (const info of infos) { - const name = info.get_name(); - directories[name] = `${file.get_uri()}${name}/`; - } - - return directories; - } - - _onAskQuestion(op, message, choices) { - op.reply(Gio.MountOperationResult.HANDLED); - } - - _onAskPassword(op, message, user, domain, flags) { - op.reply(Gio.MountOperationResult.HANDLED); - } - - /** - * Handle an error reported by the remote device. - * - * @param {Core.Packet} packet - a `kdeconnect.sftp` - */ - _handleError(packet) { - this.device.showNotification({ - id: 'sftp-error', - title: _('%s reported an error').format(this.device.name), - body: packet.body.errorMessage, - icon: new Gio.ThemedIcon({name: 'dialog-error-symbolic'}), - priority: Gio.NotificationPriority.HIGH, - }); - } - - /** - * Mount the remote device using the provided information. - * - * @param {Core.Packet} packet - a `kdeconnect.sftp` - */ - async _handleMount(packet) { - try { - // Already mounted or mounting - if (this.gmount !== null || this._mounting) - return; - - this._mounting = true; - - // Ensure the private key is in the keyring - await this._addPrivateKey(); - - // Create a new mount operation - const op = new Gio.MountOperation({ - username: packet.body.user || null, - password: packet.body.password || null, - password_save: Gio.PasswordSave.NEVER, - }); - - op.connect('ask-question', this._onAskQuestion); - op.connect('ask-password', this._onAskPassword); - - // This is the actual call to mount the device - const host = this.device.channel.host; - const uri = `sftp://${host}:${packet.body.port}/`; - const file = Gio.File.new_for_uri(uri); - - await file.mount_enclosing_volume(GLib.PRIORITY_DEFAULT, op, - this.cancellable); - } catch (e) { - // Special case when the GMount didn't unmount properly but is still - // on the same port and can be reused. - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.ALREADY_MOUNTED)) - return; - - // There's a good chance this is a host key verification error; - // regardless we'll remove the key for security. - this._removeHostKey(this.device.channel.host); - logError(e, this.device.name); - } finally { - this._mounting = false; - } - } - - /** - * Add GSConnect's private key identity to the authentication agent so our - * identity can be verified by Android during private key authentication. - * - * @return {Promise} A promise for the operation - */ - async _addPrivateKey() { - const ssh_add = this._launcher.spawnv([ - Config.SSHADD_PATH, - GLib.build_filenamev([Config.CONFIGDIR, 'private.pem']), - ]); - - const [stdout] = await ssh_add.communicate_utf8_async(null, - this.cancellable); - - if (ssh_add.get_exit_status() !== 0) - debug(stdout.trim(), this.device.name); - } - - /** - * Remove all host keys from ~/.ssh/known_hosts for @host in the port range - * used by KDE Connect (1739-1764). - * - * @param {string} host - A hostname or IP address - */ - async _removeHostKey(host) { - for (let port = 1739; port <= 1764; port++) { - try { - const ssh_keygen = this._launcher.spawnv([ - Config.SSHKEYGEN_PATH, - '-R', - `[${host}]:${port}`, - ]); - - const [stdout] = await ssh_keygen.communicate_utf8_async(null, - this.cancellable); - - const status = ssh_keygen.get_exit_status(); - - if (status !== 0) { - throw new Gio.IOErrorEnum({ - code: Gio.io_error_from_errno(status), - message: `${GLib.strerror(status)}\n${stdout}`.trim(), - }); - } - } catch (e) { - logError(e, this.device.name); - } - } - } - - /* - * Mount menu helpers - */ - _getUnmountSection() { - if (this._unmountSection === undefined) { - this._unmountSection = new Gio.Menu(); - - const unmountItem = new Gio.MenuItem(); - unmountItem.set_label(Metadata.actions.unmount.label); - unmountItem.set_icon(new Gio.ThemedIcon({ - name: Metadata.actions.unmount.icon_name, - })); - unmountItem.set_detailed_action('device.unmount'); - this._unmountSection.append_item(unmountItem); - } - - return this._unmountSection; - } - - _getFilesMenuItem() { - if (this._filesMenuItem === undefined) { - // Files menu icon - const emblem = new Gio.Emblem({ - icon: new Gio.ThemedIcon({name: 'emblem-default'}), - }); - - const mountedIcon = new Gio.EmblemedIcon({ - gicon: new Gio.ThemedIcon({name: 'folder-remote-symbolic'}), - }); - mountedIcon.add_emblem(emblem); - - // Files menu item - this._filesMenuItem = new Gio.MenuItem(); - this._filesMenuItem.set_detailed_action('device.mount'); - this._filesMenuItem.set_icon(mountedIcon); - this._filesMenuItem.set_label(_('Files')); - } - - return this._filesMenuItem; - } - - async _addSubmenu(mount) { - try { - const directories = await this._listDirectories(mount); - - // Submenu sections - const dirSection = new Gio.Menu(); - const unmountSection = this._getUnmountSection(); - - for (const [name, uri] of Object.entries(directories)) - dirSection.append(name, `device.openPath::${uri}`); - - // Files submenu - const filesSubmenu = new Gio.Menu(); - filesSubmenu.append_section(null, dirSection); - filesSubmenu.append_section(null, unmountSection); - - // Files menu item - const filesMenuItem = this._getFilesMenuItem(); - filesMenuItem.set_submenu(filesSubmenu); - - // Replace the existing menu item - const index = this.device.removeMenuAction('device.mount'); - this.device.addMenuItem(filesMenuItem, index); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - debug(e, this.device.name); - - // Reset to allow retrying - this._gmount = null; - } - } - - _removeSubmenu() { - try { - const index = this.device.removeMenuAction('device.mount'); - const action = this.device.lookup_action('mount'); - - if (action !== null) { - this.device.addMenuAction( - action, - index, - Metadata.actions.mount.label, - Metadata.actions.mount.icon_name - ); - } - } catch (e) { - logError(e, this.device.name); - } - } - - /** - * Create a symbolic link referring to the device by name - * - * @param {Gio.Mount} mount - A GMount to link to - */ - async _addSymlink(mount) { - try { - const by_name_dir = Gio.File.new_for_path( - `${Config.RUNTIMEDIR}/by-name/` - ); - - try { - by_name_dir.make_directory_with_parents(null); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS)) - throw e; - } - - // Replace path separator with a Unicode lookalike: - let safe_device_name = this.device.name.replace('/', '∕'); - - if (safe_device_name === '.') - safe_device_name = '·'; - else if (safe_device_name === '..') - safe_device_name = '··'; - - const link_target = mount.get_root().get_path(); - const link = Gio.File.new_for_path( - `${by_name_dir.get_path()}/${safe_device_name}`); - - // Check for and remove any existing stale link - try { - const link_stat = await link.query_info_async( - 'standard::symlink-target', - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - GLib.PRIORITY_DEFAULT, - this.cancellable); - - if (link_stat.get_symlink_target() === link_target) - return; - - await link.delete_async(GLib.PRIORITY_DEFAULT, - this.cancellable); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - throw e; - } - - link.make_symbolic_link(link_target, this.cancellable); - } catch (e) { - debug(e, this.device.name); - } - } - - /** - * Send a request to mount the remote device - */ - mount() { - if (this.gmount !== null) - return; - - this.device.sendPacket({ - type: 'kdeconnect.sftp.request', - body: { - startBrowsing: true, - }, - }); - } - - /** - * Remove the menu items, unmount the filesystem, replace the mount item - */ - async unmount() { - try { - if (this.gmount === null) - return; - - this._removeSubmenu(); - this._mounting = false; - - await this.gmount.unmount_with_operation( - Gio.MountUnmountFlags.FORCE, - new Gio.MountOperation(), - this.cancellable); - } catch (e) { - debug(e, this.device.name); - } - } - - destroy() { - if (this._volumeMonitor) { - this._volumeMonitor.disconnect(this._mountAddedId); - this._volumeMonitor.disconnect(this._mountRemovedId); - this._volumeMonitor = null; - } - - super.destroy(); - } -}); - -export default SFTPPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/share.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/share.js deleted file mode 100755 index 73963971..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/share.js +++ /dev/null @@ -1,492 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import Plugin from '../plugin.js'; -import * as URI from '../utils/uri.js'; - - -export const Metadata = { - label: _('Share'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Share', - description: _('Share files and URLs between devices'), - incomingCapabilities: ['kdeconnect.share.request'], - outgoingCapabilities: ['kdeconnect.share.request'], - actions: { - share: { - label: _('Share'), - icon_name: 'send-to-symbolic', - - parameter_type: null, - incoming: [], - outgoing: ['kdeconnect.share.request'], - }, - shareFile: { - label: _('Share File'), - icon_name: 'document-send-symbolic', - - parameter_type: new GLib.VariantType('(sb)'), - incoming: [], - outgoing: ['kdeconnect.share.request'], - }, - shareText: { - label: _('Share Text'), - icon_name: 'send-to-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.share.request'], - }, - shareUri: { - label: _('Share Link'), - icon_name: 'send-to-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.share.request'], - }, - }, -}; - - -/** - * Share Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/share - * - * TODO: receiving 'text' TODO: Window with textview & 'Copy to Clipboard.. - * https://github.com/KDE/kdeconnect-kde/commit/28f11bd5c9a717fb9fbb3f02ddd6cea62021d055 - */ -const SharePlugin = GObject.registerClass({ - GTypeName: 'GSConnectSharePlugin', -}, class SharePlugin extends Plugin { - - _init(device) { - super._init(device, 'share'); - } - - handlePacket(packet) { - // TODO: composite jobs (lastModified, numberOfFiles, totalPayloadSize) - if (packet.body.hasOwnProperty('filename')) { - if (this.settings.get_boolean('receive-files')) - this._handleFile(packet); - else - this._refuseFile(packet); - } else if (packet.body.hasOwnProperty('text')) { - this._handleText(packet); - } else if (packet.body.hasOwnProperty('url')) { - this._handleUri(packet); - } - } - - _ensureReceiveDirectory() { - let receiveDir = this.settings.get_string('receive-directory'); - - // Ensure a directory is set - if (receiveDir.length === 0) { - receiveDir = GLib.get_user_special_dir( - GLib.UserDirectory.DIRECTORY_DOWNLOAD - ); - - // Fallback to ~/Downloads - const homeDir = GLib.get_home_dir(); - - if (!receiveDir || receiveDir === homeDir) - receiveDir = GLib.build_filenamev([homeDir, 'Downloads']); - - this.settings.set_string('receive-directory', receiveDir); - } - - // Ensure the directory exists - if (!GLib.file_test(receiveDir, GLib.FileTest.IS_DIR)) - GLib.mkdir_with_parents(receiveDir, 448); - - return receiveDir; - } - - _getFile(filename) { - const dirpath = this._ensureReceiveDirectory(); - const basepath = GLib.build_filenamev([dirpath, filename]); - let filepath = basepath; - let copyNum = 0; - - while (GLib.file_test(filepath, GLib.FileTest.EXISTS)) - filepath = `${basepath} (${++copyNum})`; - - return Gio.File.new_for_path(filepath); - } - - _refuseFile(packet) { - try { - this.device.rejectTransfer(packet); - - this.device.showNotification({ - id: `${Date.now()}`, - title: _('Transfer Failed'), - // TRANSLATORS: eg. Google Pixel is not allowed to upload files - body: _('%s is not allowed to upload files').format( - this.device.name - ), - icon: new Gio.ThemedIcon({name: 'dialog-error-symbolic'}), - }); - } catch (e) { - debug(e, this.device.name); - } - } - - async _handleFile(packet) { - try { - const file = this._getFile(packet.body.filename); - - // Create the transfer - const transfer = this.device.createTransfer(); - - transfer.addFile(packet, file); - - // Notify that we're about to start the transfer - this.device.showNotification({ - id: transfer.uuid, - title: _('Transferring File'), - // TRANSLATORS: eg. Receiving 'book.pdf' from Google Pixel - body: _('Receiving “%s” from %s').format( - packet.body.filename, - this.device.name - ), - buttons: [{ - label: _('Cancel'), - action: 'cancelTransfer', - parameter: new GLib.Variant('s', transfer.uuid), - }], - icon: new Gio.ThemedIcon({name: 'document-save-symbolic'}), - }); - - // We'll show a notification (success or failure) - let title, body, action, iconName; - let buttons = []; - - try { - await transfer.start(); - - title = _('Transfer Successful'); - // TRANSLATORS: eg. Received 'book.pdf' from Google Pixel - body = _('Received “%s” from %s').format( - packet.body.filename, - this.device.name - ); - action = { - name: 'showPathInFolder', - parameter: new GLib.Variant('s', file.get_uri()), - }; - buttons = [ - { - label: _('Show File Location'), - action: 'showPathInFolder', - parameter: new GLib.Variant('s', file.get_uri()), - }, - { - label: _('Open File'), - action: 'openPath', - parameter: new GLib.Variant('s', file.get_uri()), - }, - ]; - iconName = 'document-save-symbolic'; - - if (packet.body.open) { - const uri = file.get_uri(); - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } - } catch (e) { - debug(e, this.device.name); - - title = _('Transfer Failed'); - // TRANSLATORS: eg. Failed to receive 'book.pdf' from Google Pixel - body = _('Failed to receive “%s” from %s').format( - packet.body.filename, - this.device.name - ); - iconName = 'dialog-warning-symbolic'; - - // Clean up the downloaded file on failure - file.delete_async(GLib.PRIORITY_DEAFAULT, null, null); - } - - this.device.hideNotification(transfer.uuid); - this.device.showNotification({ - id: transfer.uuid, - title: title, - body: body, - action: action, - buttons: buttons, - icon: new Gio.ThemedIcon({name: iconName}), - }); - } catch (e) { - logError(e, this.device.name); - } - } - - _handleUri(packet) { - const uri = packet.body.url; - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } - - _handleText(packet) { - const dialog = new Gtk.MessageDialog({ - text: _('Text Shared By %s').format(this.device.name), - secondary_text: URI.linkify(packet.body.text), - secondary_use_markup: true, - buttons: Gtk.ButtonsType.CLOSE, - }); - dialog.message_area.get_children()[1].selectable = true; - dialog.set_keep_above(true); - dialog.connect('response', (dialog) => dialog.destroy()); - dialog.show(); - } - - /** - * Open the file chooser dialog for selecting a file or inputing a URI. - */ - share() { - const dialog = new FileChooserDialog(this.device); - dialog.show(); - } - - /** - * Share local file path or URI - * - * @param {string} path - Local file path or URI - * @param {boolean} open - Whether the file should be opened after transfer - */ - async shareFile(path, open = false) { - try { - let file = null; - - if (path.includes('://')) - file = Gio.File.new_for_uri(path); - else - file = Gio.File.new_for_path(path); - - // Create the transfer - const transfer = this.device.createTransfer(); - - transfer.addFile({ - type: 'kdeconnect.share.request', - body: { - filename: file.get_basename(), - open: open, - }, - }, file); - - // Notify that we're about to start the transfer - this.device.showNotification({ - id: transfer.uuid, - title: _('Transferring File'), - // TRANSLATORS: eg. Sending 'book.pdf' to Google Pixel - body: _('Sending “%s” to %s').format( - file.get_basename(), - this.device.name - ), - buttons: [{ - label: _('Cancel'), - action: 'cancelTransfer', - parameter: new GLib.Variant('s', transfer.uuid), - }], - icon: new Gio.ThemedIcon({name: 'document-send-symbolic'}), - }); - - // We'll show a notification (success or failure) - let title, body, iconName; - - try { - await transfer.start(); - - title = _('Transfer Successful'); - // TRANSLATORS: eg. Sent "book.pdf" to Google Pixel - body = _('Sent “%s” to %s').format( - file.get_basename(), - this.device.name - ); - iconName = 'document-send-symbolic'; - } catch (e) { - debug(e, this.device.name); - - title = _('Transfer Failed'); - // TRANSLATORS: eg. Failed to send "book.pdf" to Google Pixel - body = _('Failed to send “%s” to %s').format( - file.get_basename(), - this.device.name - ); - iconName = 'dialog-warning-symbolic'; - } - - this.device.hideNotification(transfer.uuid); - this.device.showNotification({ - id: transfer.uuid, - title: title, - body: body, - icon: new Gio.ThemedIcon({name: iconName}), - }); - } catch (e) { - debug(e, this.device.name); - } - } - - /** - * Share a string of text. Remote behaviour is undefined. - * - * @param {string} text - A string of unicode text - */ - shareText(text) { - this.device.sendPacket({ - type: 'kdeconnect.share.request', - body: {text: text}, - }); - } - - /** - * Share a URI. Generally the remote device opens it with the scheme default - * - * @param {string} uri - A URI to share - */ - shareUri(uri) { - if (GLib.uri_parse_scheme(uri) === 'file') { - this.shareFile(uri); - return; - } - - this.device.sendPacket({ - type: 'kdeconnect.share.request', - body: {url: uri}, - }); - } -}); - - -/** A simple FileChooserDialog for sharing files */ -const FileChooserDialog = GObject.registerClass({ - GTypeName: 'GSConnectShareFileChooserDialog', -}, class FileChooserDialog extends Gtk.FileChooserDialog { - - _init(device) { - super._init({ - // TRANSLATORS: eg. Send files to Google Pixel - title: _('Send files to %s').format(device.name), - select_multiple: true, - extra_widget: new Gtk.CheckButton({ - // TRANSLATORS: Mark the file to be opened once completed - label: _('Open when done'), - visible: true, - }), - use_preview_label: false, - }); - - this.device = device; - - // Align checkbox with sidebar - const box = this.get_content_area().get_children()[0].get_children()[0]; - const paned = box.get_children()[0]; - paned.bind_property( - 'position', - this.extra_widget, - 'margin-left', - GObject.BindingFlags.SYNC_CREATE - ); - - // Preview Widget - this.preview_widget = new Gtk.Image(); - this.preview_widget_active = false; - this.connect('update-preview', this._onUpdatePreview); - - // URI entry - this._uriEntry = new Gtk.Entry({ - placeholder_text: 'https://', - hexpand: true, - visible: true, - }); - this._uriEntry.connect('activate', this._sendLink.bind(this)); - - // URI/File toggle - this._uriButton = new Gtk.ToggleButton({ - image: new Gtk.Image({ - icon_name: 'web-browser-symbolic', - pixel_size: 16, - }), - valign: Gtk.Align.CENTER, - // TRANSLATORS: eg. Send a link to Google Pixel - tooltip_text: _('Send a link to %s').format(device.name), - visible: true, - }); - this._uriButton.connect('toggled', this._onUriButtonToggled.bind(this)); - - this.add_button(_('Cancel'), Gtk.ResponseType.CANCEL); - const sendButton = this.add_button(_('Send'), Gtk.ResponseType.OK); - sendButton.connect('clicked', this._sendLink.bind(this)); - - this.get_header_bar().pack_end(this._uriButton); - this.set_default_response(Gtk.ResponseType.OK); - } - - _onUpdatePreview(chooser) { - try { - const pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( - chooser.get_preview_filename(), - chooser.get_scale_factor() * 128, - -1 - ); - chooser.preview_widget.pixbuf = pixbuf; - chooser.preview_widget.visible = true; - chooser.preview_widget_active = true; - } catch (e) { - chooser.preview_widget.visible = false; - chooser.preview_widget_active = false; - } - } - - _onUriButtonToggled(button) { - const header = this.get_header_bar(); - - // Show the URL entry - if (button.active) { - this.extra_widget.sensitive = false; - header.set_custom_title(this._uriEntry); - this.set_response_sensitive(Gtk.ResponseType.OK, true); - - // Hide the URL entry - } else { - header.set_custom_title(null); - this.set_response_sensitive( - Gtk.ResponseType.OK, - this.get_uris().length > 1 - ); - this.extra_widget.sensitive = true; - } - } - - _sendLink(widget) { - if (this._uriButton.active && this._uriEntry.text.length) - this.response(1); - } - - vfunc_response(response_id) { - if (response_id === Gtk.ResponseType.OK) { - for (const uri of this.get_uris()) { - const parameter = new GLib.Variant( - '(sb)', - [uri, this.extra_widget.active] - ); - this.device.activate_action('shareFile', parameter); - } - } else if (response_id === 1) { - const parameter = new GLib.Variant('s', this._uriEntry.text); - this.device.activate_action('shareUri', parameter); - } - - this.destroy(); - } -}); - -export default SharePlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/sms.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/sms.js deleted file mode 100755 index 4a359fd2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/sms.js +++ /dev/null @@ -1,536 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Plugin from '../plugin.js'; -import LegacyMessagingDialog from '../ui/legacyMessaging.js'; -import * as Messaging from '../ui/messaging.js'; -import SmsURI from '../utils/uri.js'; - - -export const Metadata = { - label: _('SMS'), - description: _('Send and read SMS of the paired device and be notified of new SMS'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SMS', - incomingCapabilities: [ - 'kdeconnect.sms.messages', - ], - outgoingCapabilities: [ - 'kdeconnect.sms.request', - 'kdeconnect.sms.request_conversation', - 'kdeconnect.sms.request_conversations', - ], - actions: { - // SMS Actions - sms: { - label: _('Messaging'), - icon_name: 'sms-symbolic', - - parameter_type: null, - incoming: [], - outgoing: ['kdeconnect.sms.request'], - }, - uriSms: { - label: _('New SMS (URI)'), - icon_name: 'sms-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.sms.request'], - }, - replySms: { - label: _('Reply SMS'), - icon_name: 'sms-symbolic', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.sms.request'], - }, - sendMessage: { - label: _('Send Message'), - icon_name: 'sms-send', - - parameter_type: new GLib.VariantType('(aa{sv})'), - incoming: [], - outgoing: ['kdeconnect.sms.request'], - }, - sendSms: { - label: _('Send SMS'), - icon_name: 'sms-send', - - parameter_type: new GLib.VariantType('(ss)'), - incoming: [], - outgoing: ['kdeconnect.sms.request'], - }, - shareSms: { - label: _('Share SMS'), - icon_name: 'sms-send', - - parameter_type: new GLib.VariantType('s'), - incoming: [], - outgoing: ['kdeconnect.sms.request'], - }, - }, -}; - - -/** - * SMS Message event type. Currently all events are TEXT_MESSAGE. - * - * TEXT_MESSAGE: Has a "body" field which contains pure, human-readable text - */ -export const MessageEventType = { - TEXT_MESSAGE: 0x1, -}; - - -/** - * SMS Message status. READ/UNREAD match the 'read' field from the Android App - * message packet. - * - * UNREAD: A message not marked as read - * READ: A message marked as read - */ -export const MessageStatus = { - UNREAD: 0, - READ: 1, -}; - - -/** - * SMS Message type, set from the 'type' field in the Android App - * message packet. - * - * See: https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns.html - * - * ALL: all messages - * INBOX: Received messages - * SENT: Sent messages - * DRAFT: Message drafts - * OUTBOX: Outgoing messages - * FAILED: Failed outgoing messages - * QUEUED: Messages queued to send later - */ -export const MessageBox = { - ALL: 0, - INBOX: 1, - SENT: 2, - DRAFT: 3, - OUTBOX: 4, - FAILED: 5, - QUEUED: 6, -}; - - -/** - * SMS Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/sms - * https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SMSPlugin/ - */ -const SMSPlugin = GObject.registerClass({ - GTypeName: 'GSConnectSMSPlugin', - Properties: { - 'threads': GObject.param_spec_variant( - 'threads', - 'Conversation List', - 'A list of threads', - new GLib.VariantType('aa{sv}'), - null, - GObject.ParamFlags.READABLE - ), - }, -}, class SMSPlugin extends Plugin { - - _init(device) { - super._init(device, 'sms'); - - this.cacheProperties(['_threads']); - } - - get threads() { - if (this._threads === undefined) - this._threads = {}; - - return this._threads; - } - - get window() { - if (this.settings.get_boolean('legacy-sms')) { - return new LegacyMessagingDialog({ - device: this.device, - plugin: this, - }); - } - - if (this._window === undefined) { - this._window = new Messaging.Window({ - application: Gio.Application.get_default(), - device: this.device, - plugin: this, - }); - - this._window.connect('destroy', () => { - this._window = undefined; - }); - } - - return this._window; - } - - clearCache() { - this._threads = {}; - this.notify('threads'); - } - - cacheLoaded() { - this.notify('threads'); - } - - connected() { - super.connected(); - this._requestConversations(); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.sms.messages': - this._handleMessages(packet.body.messages); - break; - } - } - - /** - * Handle a digest of threads. - * - * @param {Object[]} messages - A list of message objects - * @param {string[]} thread_ids - A list of thread IDs as strings - */ - _handleDigest(messages, thread_ids) { - // Prune threads - for (const thread_id of Object.keys(this.threads)) { - if (!thread_ids.includes(thread_id)) - delete this.threads[thread_id]; - } - - // Request each new or newer thread - for (let i = 0, len = messages.length; i < len; i++) { - const message = messages[i]; - const cache = this.threads[message.thread_id]; - - if (cache === undefined) { - this._requestConversation(message.thread_id); - continue; - } - - // If this message is marked read, mark the rest as read - if (message.read === MessageStatus.READ) { - for (const msg of cache) - msg.read = MessageStatus.READ; - } - - // If we don't have a thread for this message or it's newer - // than the last message in the cache, request the thread - if (!cache.length || cache[cache.length - 1].date < message.date) - this._requestConversation(message.thread_id); - } - - this.notify('threads'); - } - - /** - * Handle a new single message - * - * @param {Object} message - A message object - */ - _handleMessage(message) { - let conversation = null; - - // If the window is open, try and find an active conversation - if (this._window) - conversation = this._window.getConversationForMessage(message); - - // If there's an active conversation, we should log the message now - if (conversation) - conversation.logNext(message); - } - - /** - * Parse a conversation (thread of messages) and sort them - * - * @param {Object[]} thread - A list of sms message objects from a thread - */ - _handleThread(thread) { - // If there are no addresses this will cause major problems... - if (!thread[0].addresses || !thread[0].addresses[0]) - return; - - const thread_id = thread[0].thread_id; - const cache = this.threads[thread_id] || []; - - // Handle each message - for (let i = 0, len = thread.length; i < len; i++) { - const message = thread[i]; - - // TODO: We only cache messages of a known MessageBox since we - // have no reliable way to determine its direction, let alone - // what to do with it. - if (message.type < 0 || message.type > 6) - continue; - - // If the message exists, just update it - const cacheMessage = cache.find(m => m.date === message.date); - - if (cacheMessage) { - Object.assign(cacheMessage, message); - } else { - cache.push(message); - this._handleMessage(message); - } - } - - // Sort the thread by ascending date and notify - this.threads[thread_id] = cache.sort((a, b) => a.date - b.date); - this.notify('threads'); - } - - /** - * Handle a response to telephony.request_conversation(s) - * - * @param {Object[]} messages - A list of sms message objects - */ - _handleMessages(messages) { - try { - // If messages is empty there's nothing to do... - if (messages.length === 0) - return; - - const thread_ids = []; - - // Perform some modification of the messages - for (let i = 0, len = messages.length; i < len; i++) { - const message = messages[i]; - - // COERCION: thread_id's to strings - message.thread_id = `${message.thread_id}`; - thread_ids.push(message.thread_id); - - // TODO: Remove bogus `insert-address-token` entries - let a = message.addresses.length; - - while (a--) { - if (message.addresses[a].address === undefined || - message.addresses[a].address === 'insert-address-token') - message.addresses.splice(a, 1); - } - } - - // If there's multiple thread_id's it's a summary of threads - if (thread_ids.some(id => id !== thread_ids[0])) - this._handleDigest(messages, thread_ids); - - // Otherwise this is single thread or new message - else - this._handleThread(messages); - } catch (e) { - debug(e, this.device.name); - } - } - - /** - * Request a list of messages from a single thread. - * - * @param {number} thread_id - The id of the thread to request - */ - _requestConversation(thread_id) { - this.device.sendPacket({ - type: 'kdeconnect.sms.request_conversation', - body: { - threadID: thread_id, - }, - }); - } - - /** - * Request a list of the last message in each unarchived thread. - */ - _requestConversations() { - this.device.sendPacket({ - type: 'kdeconnect.sms.request_conversations', - }); - } - - /** - * A notification action for replying to SMS messages (or missed calls). - * - * @param {string} hint - Could be either a contact name or phone number - */ - replySms(hint) { - this.window.present(); - // FIXME: causes problems now that non-numeric addresses are allowed - // this.window.address = hint.toPhoneNumber(); - } - - /** - * Send an SMS message - * - * @param {string} phoneNumber - The phone number to send the message to - * @param {string} messageBody - The message to send - */ - sendSms(phoneNumber, messageBody) { - this.device.sendPacket({ - type: 'kdeconnect.sms.request', - body: { - sendSms: true, - phoneNumber: phoneNumber, - messageBody: messageBody, - }, - }); - } - - /** - * Send a message - * - * @param {Object[]} addresses - A list of address objects - * @param {string} messageBody - The message text - * @param {number} [event] - An event bitmask - * @param {boolean} [forceSms] - Whether to force SMS - * @param {number} [subId] - The SIM card to use - */ - sendMessage(addresses, messageBody, event = 1, forceSms = false, subId = undefined) { - // TODO: waiting on support in kdeconnect-android - // if (this._version === 1) { - this.device.sendPacket({ - type: 'kdeconnect.sms.request', - body: { - sendSms: true, - phoneNumber: addresses[0].address, - messageBody: messageBody, - }, - }); - // } else if (this._version === 2) { - // this.device.sendPacket({ - // type: 'kdeconnect.sms.request', - // body: { - // version: 2, - // addresses: addresses, - // messageBody: messageBody, - // forceSms: forceSms, - // sub_id: subId - // } - // }); - // } - } - - /** - * Share a text content by SMS message. This is used by the WebExtension to - * share URLs from the browser, but could be used to initiate sharing of any - * text content. - * - * @param {string} url - The link to be shared - */ - shareSms(url) { - // Legacy Mode - if (this.settings.get_boolean('legacy-sms')) { - const window = this.window; - window.present(); - window.setMessage(url); - - // If there are active threads, show the chooser dialog - } else if (Object.values(this.threads).length > 0) { - const window = new Messaging.ConversationChooser({ - application: Gio.Application.get_default(), - device: this.device, - message: url, - plugin: this, - }); - - window.present(); - - // Otherwise show the window and wait for a contact to be chosen - } else { - this.window.present(); - this.window.setMessage(url, true); - } - } - - /** - * Open and present the messaging window - */ - sms() { - this.window.present(); - } - - /** - * This is the sms: URI scheme handler - * - * @param {string} uri - The URI the handle (sms:|sms://|sms:///) - */ - uriSms(uri) { - try { - uri = new SmsURI(uri); - - // Lookup contacts - const addresses = uri.recipients.map(number => { - return {address: number.toPhoneNumber()}; - }); - const contacts = this.device.contacts.lookupAddresses(addresses); - - // Present the window and show the conversation - const window = this.window; - window.present(); - window.setContacts(contacts); - - // Set the outgoing message if the uri has a body variable - if (uri.body) - window.setMessage(uri.body); - } catch (e) { - debug(e, `${this.device.name}: "${uri}"`); - } - } - - _threadHasAddress(thread, addressObj) { - const number = addressObj.address.toPhoneNumber(); - - for (const taddressObj of thread[0].addresses) { - const tnumber = taddressObj.address.toPhoneNumber(); - - if (number.endsWith(tnumber) || tnumber.endsWith(number)) - return true; - } - - return false; - } - - /** - * Try to find a thread_id in @smsPlugin for @addresses. - * - * @param {Object[]} addresses - a list of address objects - * @return {string|null} a thread ID - */ - getThreadIdForAddresses(addresses = []) { - const threads = Object.values(this.threads); - - for (const thread of threads) { - if (addresses.length !== thread[0].addresses.length) - continue; - - if (addresses.every(addressObj => this._threadHasAddress(thread, addressObj))) - return thread[0].thread_id; - } - - return null; - } - - destroy() { - if (this._window !== undefined) - this._window.destroy(); - - super.destroy(); - } -}); - -export default SMSPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/systemvolume.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/systemvolume.js deleted file mode 100755 index 9db02d1d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/systemvolume.js +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import Config from '../../config.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('System Volume'), - description: _('Enable the paired device to control the system volume'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.SystemVolume', - incomingCapabilities: ['kdeconnect.systemvolume.request'], - outgoingCapabilities: ['kdeconnect.systemvolume'], - actions: {}, -}; - - -/** - * SystemVolume Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/systemvolume - * https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/SystemvolumePlugin/ - */ -const SystemVolumePlugin = GObject.registerClass({ - GTypeName: 'GSConnectSystemVolumePlugin', -}, class SystemVolumePlugin extends Plugin { - - _init(device) { - super._init(device, 'systemvolume'); - - // Cache stream properties - this._cache = new WeakMap(); - - // Connect to the mixer - try { - this._mixer = Components.acquire('pulseaudio'); - - this._streamChangedId = this._mixer.connect( - 'stream-changed', - this._sendSink.bind(this) - ); - - this._outputAddedId = this._mixer.connect( - 'output-added', - this._sendSinkList.bind(this) - ); - - this._outputRemovedId = this._mixer.connect( - 'output-removed', - this._sendSinkList.bind(this) - ); - - // Modify the error to redirect to the wiki - } catch (e) { - e.name = _('PulseAudio not found'); - e.url = `${Config.PACKAGE_URL}/wiki/Error#pulseaudio-not-found`; - throw e; - } - } - - handlePacket(packet) { - switch (true) { - case packet.body.hasOwnProperty('requestSinks'): - this._sendSinkList(); - break; - - case packet.body.hasOwnProperty('name'): - this._changeSink(packet); - break; - } - } - - connected() { - super.connected(); - - this._sendSinkList(); - } - - /** - * Handle a request to change an output - * - * @param {Core.Packet} packet - a `kdeconnect.systemvolume.request` - */ - _changeSink(packet) { - let stream; - - for (const sink of this._mixer.get_sinks()) { - if (sink.name === packet.body.name) { - stream = sink; - break; - } - } - - // No sink with the given name - if (stream === undefined) { - this._sendSinkList(); - return; - } - - // Get a cache and store volume and mute states if changed - const cache = this._cache.get(stream) || {}; - - if (packet.body.hasOwnProperty('muted')) { - cache.muted = packet.body.muted; - this._cache.set(stream, cache); - stream.change_is_muted(packet.body.muted); - } - - if (packet.body.hasOwnProperty('volume')) { - cache.volume = packet.body.volume; - this._cache.set(stream, cache); - stream.volume = packet.body.volume; - stream.push_volume(); - } - } - - /** - * Update the cache for @stream - * - * @param {Gvc.MixerStream} stream - The stream to cache - * @return {Object} The updated cache object - */ - _updateCache(stream) { - const state = { - name: stream.name, - description: stream.display_name, - muted: stream.is_muted, - volume: stream.volume, - maxVolume: this._mixer.get_vol_max_norm(), - }; - - this._cache.set(stream, state); - - return state; - } - - /** - * Send the state of a local sink - * - * @param {Gvc.MixerControl} mixer - The mixer that owns the stream - * @param {number} id - The Id of the stream that changed - */ - _sendSink(mixer, id) { - // Avoid starving the packet channel when fading - if (this._mixer.fading) - return; - - // Check the cache - const stream = this._mixer.lookup_stream_id(id); - const cache = this._cache.get(stream) || {}; - - // If the port has changed we have to send the whole list to update the - // display name - if (!cache.display_name || cache.display_name !== stream.display_name) { - this._sendSinkList(); - return; - } - - // If only volume and/or mute are set, send a single update - if (cache.volume !== stream.volume || cache.muted !== stream.is_muted) { - // Update the cache - const state = this._updateCache(stream); - - // Send the stream update - this.device.sendPacket({ - type: 'kdeconnect.systemvolume', - body: state, - }); - } - } - - /** - * Send a list of local sinks - */ - _sendSinkList() { - const sinkList = this._mixer.get_sinks().map(sink => { - return this._updateCache(sink); - }); - - // Send the sinkList - this.device.sendPacket({ - type: 'kdeconnect.systemvolume', - body: { - sinkList: sinkList, - }, - }); - } - - destroy() { - if (this._mixer !== undefined) { - this._mixer.disconnect(this._streamChangedId); - this._mixer.disconnect(this._outputAddedId); - this._mixer.disconnect(this._outputRemovedId); - this._mixer = Components.release('pulseaudio'); - } - - super.destroy(); - } -}); - -export default SystemVolumePlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/telephony.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/telephony.js deleted file mode 100755 index af1dae16..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/plugins/telephony.js +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import * as Components from '../components/index.js'; -import Plugin from '../plugin.js'; - - -export const Metadata = { - label: _('Telephony'), - description: _('Be notified about calls and adjust system volume during ringing/ongoing calls'), - id: 'org.gnome.Shell.Extensions.GSConnect.Plugin.Telephony', - incomingCapabilities: [ - 'kdeconnect.telephony', - ], - outgoingCapabilities: [ - 'kdeconnect.telephony.request', - 'kdeconnect.telephony.request_mute', - ], - actions: { - muteCall: { - // TRANSLATORS: Silence the actively ringing call - label: _('Mute Call'), - icon_name: 'audio-volume-muted-symbolic', - - parameter_type: null, - incoming: ['kdeconnect.telephony'], - outgoing: ['kdeconnect.telephony.request_mute'], - }, - }, -}; - - -/** - * Telephony Plugin - * https://github.com/KDE/kdeconnect-kde/tree/master/plugins/telephony - * https://github.com/KDE/kdeconnect-android/tree/master/src/org/kde/kdeconnect/Plugins/TelephonyPlugin - */ -const TelephonyPlugin = GObject.registerClass({ - GTypeName: 'GSConnectTelephonyPlugin', -}, class TelephonyPlugin extends Plugin { - - _init(device) { - super._init(device, 'telephony'); - - // Neither of these are crucial for the plugin to work - this._mpris = Components.acquire('mpris'); - this._mixer = Components.acquire('pulseaudio'); - } - - handlePacket(packet) { - switch (packet.type) { - case 'kdeconnect.telephony': - this._handleEvent(packet); - break; - } - } - - /** - * Change volume, microphone and media player state in response to an - * incoming or answered call. - * - * @param {string} eventType - 'ringing' or 'talking' - */ - _setMediaState(eventType) { - // Mixer Volume - if (this._mixer !== undefined) { - switch (this.settings.get_string(`${eventType}-volume`)) { - case 'restore': - this._mixer.restore(); - break; - - case 'lower': - this._mixer.lowerVolume(); - break; - - case 'mute': - this._mixer.muteVolume(); - break; - } - - if (eventType === 'talking' && this.settings.get_boolean('talking-microphone')) - this._mixer.muteMicrophone(); - } - - // Media Playback - if (this._mpris && this.settings.get_boolean(`${eventType}-pause`)) - this._mpris.pauseAll(); - } - - /** - * Restore volume, microphone and media player state (if changed), making - * sure to unpause before raising volume. - * - * TODO: there's a possibility we might revert a media/mixer state set for - * another device. - */ - _restoreMediaState() { - // Media Playback - if (this._mpris) - this._mpris.unpauseAll(); - - // Mixer Volume - if (this._mixer) - this._mixer.restore(); - } - - /** - * Load a Gdk.Pixbuf from base64 encoded data - * - * @param {string} data - Base64 encoded JPEG data - * @return {Gdk.Pixbuf|null} A contact photo - */ - _getThumbnailPixbuf(data) { - const loader = new GdkPixbuf.PixbufLoader(); - - try { - data = GLib.base64_decode(data); - loader.write(data); - loader.close(); - } catch (e) { - debug(e, this.device.name); - } - - return loader.get_pixbuf(); - } - - /** - * Handle a telephony event (ringing, talking), showing or hiding a - * notification and possibly adjusting the media/mixer state. - * - * @param {Core.Packet} packet - A `kdeconnect.telephony` - */ - _handleEvent(packet) { - // Only handle 'ringing' or 'talking' events; leave the notification - // plugin to handle 'missedCall' since they're often repliable - if (!['ringing', 'talking'].includes(packet.body.event)) - return; - - // This is the end of a telephony event - if (packet.body.isCancel) - this._cancelEvent(packet); - else - this._notifyEvent(packet); - } - - _cancelEvent(packet) { - // Ensure we have a sender - // TRANSLATORS: No name or phone number - let sender = _('Unknown Contact'); - - if (packet.body.contactName) - sender = packet.body.contactName; - else if (packet.body.phoneNumber) - sender = packet.body.phoneNumber; - - this.device.hideNotification(`${packet.body.event}|${sender}`); - this._restoreMediaState(); - } - - _notifyEvent(packet) { - let body; - let buttons = []; - let icon = null; - let priority = Gio.NotificationPriority.NORMAL; - - // Ensure we have a sender - // TRANSLATORS: No name or phone number - let sender = _('Unknown Contact'); - - if (packet.body.contactName) - sender = packet.body.contactName; - else if (packet.body.phoneNumber) - sender = packet.body.phoneNumber; - - // If there's a photo, use it as the notification icon - if (packet.body.phoneThumbnail) - icon = this._getThumbnailPixbuf(packet.body.phoneThumbnail); - - if (icon === null) - icon = new Gio.ThemedIcon({name: 'call-start-symbolic'}); - - // Notify based based on the event type - if (packet.body.event === 'ringing') { - this._setMediaState('ringing'); - - // TRANSLATORS: The phone is ringing - body = _('Incoming call'); - buttons = [{ - action: 'muteCall', - // TRANSLATORS: Silence the actively ringing call - label: _('Mute'), - parameter: null, - }]; - priority = Gio.NotificationPriority.URGENT; - } - - if (packet.body.event === 'talking') { - this.device.hideNotification(`ringing|${sender}`); - this._setMediaState('talking'); - - // TRANSLATORS: A phone call is active - body = _('Ongoing call'); - } - - this.device.showNotification({ - id: `${packet.body.event}|${sender}`, - title: sender, - body: body, - icon: icon, - priority: priority, - buttons: buttons, - }); - } - - /** - * Silence an incoming call and restore the previous mixer/media state, if - * applicable. - */ - muteCall() { - this.device.sendPacket({ - type: 'kdeconnect.telephony.request_mute', - body: {}, - }); - - this._restoreMediaState(); - } - - destroy() { - if (this._mixer !== undefined) - this._mixer = Components.release('pulseaudio'); - - if (this._mpris !== undefined) - this._mpris = Components.release('mpris'); - - super.destroy(); - } -}); - -export default TelephonyPlugin; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/contacts.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/contacts.js deleted file mode 100755 index 3ead9600..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/contacts.js +++ /dev/null @@ -1,642 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import system from 'system'; - - -/** - * Return a random color - * - * @param {*} [salt] - If not %null, will be used as salt for generating a color - * @param {number} alpha - A value in the [0...1] range for the alpha channel - * @return {Gdk.RGBA} A new Gdk.RGBA object generated from the input - */ -function randomRGBA(salt = null, alpha = 1.0) { - let red, green, blue; - - if (salt !== null) { - const hash = new GLib.Variant('s', `${salt}`).hash(); - red = ((hash & 0xFF0000) >> 16) / 255; - green = ((hash & 0x00FF00) >> 8) / 255; - blue = (hash & 0x0000FF) / 255; - } else { - red = Math.random(); - green = Math.random(); - blue = Math.random(); - } - - return new Gdk.RGBA({red: red, green: green, blue: blue, alpha: alpha}); -} - - -/** - * Get the relative luminance of a RGB set - * See: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef - * - * @param {Gdk.RGBA} rgba - A GdkRGBA object - * @return {number} The relative luminance of the color - */ -function relativeLuminance(rgba) { - const {red, green, blue} = rgba; - - const R = (red > 0.03928) ? red / 12.92 : Math.pow(((red + 0.055) / 1.055), 2.4); - const G = (green > 0.03928) ? green / 12.92 : Math.pow(((green + 0.055) / 1.055), 2.4); - const B = (blue > 0.03928) ? blue / 12.92 : Math.pow(((blue + 0.055) / 1.055), 2.4); - - return 0.2126 * R + 0.7152 * G + 0.0722 * B; -} - - -/** - * Get a GdkRGBA contrasted for the input - * See: https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef - * - * @param {Gdk.RGBA} rgba - A GdkRGBA object for the background color - * @return {Gdk.RGBA} A GdkRGBA object for the foreground color - */ -function getFgRGBA(rgba) { - const bgLuminance = relativeLuminance(rgba); - const lightContrast = (0.07275541795665634 + 0.05) / (bgLuminance + 0.05); - const darkContrast = (bgLuminance + 0.05) / (0.0046439628482972135 + 0.05); - - const value = (darkContrast > lightContrast) ? 0.06 : 0.94; - return new Gdk.RGBA({red: value, green: value, blue: value, alpha: 0.5}); -} - - -/** - * Get a GdkPixbuf for @path, allowing the corrupt JPEG's KDE Connect sometimes - * sends. This function is synchronous. - * - * @param {string} path - A local file path - * @param {number} size - Size in pixels - * @param {scale} [scale] - Scale factor for the size - * @return {Gdk.Pixbuf} A pixbuf - */ -function getPixbufForPath(path, size, scale = 1.0) { - let data, loader; - - // Catch missing avatar files - try { - data = GLib.file_get_contents(path)[1]; - } catch (e) { - debug(e, path); - return undefined; - } - - // Consider errors from partially corrupt JPEGs to be warnings - try { - loader = new GdkPixbuf.PixbufLoader(); - loader.write(data); - loader.close(); - } catch (e) { - debug(e, path); - } - - const pixbuf = loader.get_pixbuf(); - - // Scale to monitor - size = Math.floor(size * scale); - return pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.HYPER); -} - -function getPixbufForIcon(name, size, scale, bgColor) { - const color = getFgRGBA(bgColor); - const theme = Gtk.IconTheme.get_default(); - const info = theme.lookup_icon_for_scale( - name, - size, - scale, - Gtk.IconLookupFlags.FORCE_SYMBOLIC - ); - - return info.load_symbolic(color, null, null, null)[0]; -} - - -/** - * Return a localized string for a phone number type - * See: http://www.ietf.org/rfc/rfc2426.txt - * - * @param {string} type - An RFC2426 phone number type - * @return {string} A localized string like 'Mobile' - */ -function getNumberTypeLabel(type) { - if (type.includes('fax')) - // TRANSLATORS: A fax number - return _('Fax'); - - if (type.includes('work')) - // TRANSLATORS: A work or office phone number - return _('Work'); - - if (type.includes('cell')) - // TRANSLATORS: A mobile or cellular phone number - return _('Mobile'); - - if (type.includes('home')) - // TRANSLATORS: A home phone number - return _('Home'); - - // TRANSLATORS: All other phone number types - return _('Other'); -} - -/** - * Get a display number from @contact for @address. - * - * @param {Object} contact - A contact object - * @param {string} address - A phone number - * @return {string} A (possibly) better display number for the address - */ -export function getDisplayNumber(contact, address) { - const number = address.toPhoneNumber(); - - for (const contactNumber of contact.numbers) { - const cnumber = contactNumber.value.toPhoneNumber(); - - if (number.endsWith(cnumber) || cnumber.endsWith(number)) - return GLib.markup_escape_text(contactNumber.value, -1); - } - - return GLib.markup_escape_text(address, -1); -} - - -/** - * Contact Avatar - */ -const AvatarCache = new WeakMap(); - -export const Avatar = GObject.registerClass({ - GTypeName: 'GSConnectContactAvatar', -}, class ContactAvatar extends Gtk.DrawingArea { - - _init(contact = null) { - super._init({ - height_request: 32, - width_request: 32, - valign: Gtk.Align.CENTER, - visible: true, - }); - - this.contact = contact; - } - - get rgba() { - if (this._rgba === undefined) { - if (this.contact) - this._rgba = randomRGBA(this.contact.name); - else - this._rgba = randomRGBA(GLib.uuid_string_random()); - } - - return this._rgba; - } - - get contact() { - if (this._contact === undefined) - this._contact = null; - - return this._contact; - } - - set contact(contact) { - if (this.contact === contact) - return; - - this._contact = contact; - this._surface = undefined; - this._rgba = undefined; - this._offset = 0; - } - - _loadSurface() { - // Get the monitor scale - const display = Gdk.Display.get_default(); - const monitor = display.get_monitor_at_window(this.get_window()); - const scale = monitor.get_scale_factor(); - - // If there's a contact with an avatar, try to load it - if (this.contact && this.contact.avatar) { - // Check the cache - this._surface = AvatarCache.get(this.contact); - - // Try loading the pixbuf - if (!this._surface) { - const pixbuf = getPixbufForPath( - this.contact.avatar, - this.width_request, - scale - ); - - if (pixbuf) { - this._surface = Gdk.cairo_surface_create_from_pixbuf( - pixbuf, - 0, - this.get_window() - ); - AvatarCache.set(this.contact, this._surface); - } - } - } - - // If we still don't have a surface, load a fallback - if (!this._surface) { - let iconName; - - // If we were given a contact, it's direct message otherwise group - if (this.contact) - iconName = 'avatar-default-symbolic'; - else - iconName = 'group-avatar-symbolic'; - - // Center the icon - this._offset = (this.width_request - 24) / 2; - - // Load the fallback - const pixbuf = getPixbufForIcon(iconName, 24, scale, this.rgba); - - this._surface = Gdk.cairo_surface_create_from_pixbuf( - pixbuf, - 0, - this.get_window() - ); - } - } - - vfunc_draw(cr) { - if (!this._surface) - this._loadSurface(); - - // Clip to a circle - const rad = this.width_request / 2; - cr.arc(rad, rad, rad, 0, 2 * Math.PI); - cr.clipPreserve(); - - // Fill the background if the the surface is offset - if (this._offset > 0) { - Gdk.cairo_set_source_rgba(cr, this.rgba); - cr.fill(); - } - - // Draw the avatar/icon - cr.setSourceSurface(this._surface, this._offset, this._offset); - cr.paint(); - - cr.$dispose(); - return Gdk.EVENT_PROPAGATE; - } -}); - - -/** - * A row for a contact address (usually a phone number). - */ -const AddressRow = GObject.registerClass({ - GTypeName: 'GSConnectContactsAddressRow', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/contacts-address-row.ui', - Children: ['avatar', 'name-label', 'address-label', 'type-label'], -}, class AddressRow extends Gtk.ListBoxRow { - - _init(contact, index = 0) { - super._init(); - - this._index = index; - this._number = contact.numbers[index]; - this.contact = contact; - } - - get contact() { - if (this._contact === undefined) - this._contact = null; - - return this._contact; - } - - set contact(contact) { - if (this.contact === contact) - return; - - this._contact = contact; - - if (this._index === 0) { - this.avatar.contact = contact; - this.avatar.visible = true; - - this.name_label.label = GLib.markup_escape_text(contact.name, -1); - this.name_label.visible = true; - - this.address_label.margin_start = 0; - this.address_label.margin_end = 0; - } else { - this.avatar.visible = false; - this.name_label.visible = false; - - // TODO: rtl inverts margin-start so the number don't align - this.address_label.margin_start = 38; - this.address_label.margin_end = 38; - } - - this.address_label.label = GLib.markup_escape_text(this.number.value, -1); - - if (this.number.type !== undefined) - this.type_label.label = getNumberTypeLabel(this.number.type); - } - - get number() { - if (this._number === undefined) - return {value: 'unknown', type: 'unknown'}; - - return this._number; - } -}); - - -/** - * A widget for selecting contact addresses (usually phone numbers) - */ -export const ContactChooser = GObject.registerClass({ - GTypeName: 'GSConnectContactChooser', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'store': GObject.ParamSpec.object( - 'store', - 'Store', - 'The contacts store', - GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, - GObject.Object - ), - }, - Signals: { - 'number-selected': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [GObject.TYPE_STRING], - }, - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/contact-chooser.ui', - Children: ['entry', 'list', 'scrolled'], -}, class ContactChooser extends Gtk.Grid { - - _init(params) { - super._init(params); - - // Setup the contact list - this.list._entry = this.entry.text; - this.list.set_filter_func(this._filter); - this.list.set_sort_func(this._sort); - - // Make sure we're using the correct contacts store - this.device.bind_property( - 'contacts', - this, - 'store', - GObject.BindingFlags.SYNC_CREATE - ); - - // Cleanup on ::destroy - this.connect('destroy', this._onDestroy); - } - - get store() { - if (this._store === undefined) - this._store = null; - - return this._store; - } - - set store(store) { - if (this.store === store) - return; - - // Unbind the old store - if (this._store) { - // Disconnect from the store - this._store.disconnect(this._contactAddedId); - this._store.disconnect(this._contactRemovedId); - this._store.disconnect(this._contactChangedId); - - // Clear the contact list - const rows = this.list.get_children(); - - for (let i = 0, len = rows.length; i < len; i++) { - rows[i].destroy(); - // HACK: temporary mitigator for mysterious GtkListBox leak - system.gc(); - } - } - - // Set the store - this._store = store; - - // Bind the new store - if (this._store) { - // Connect to the new store - this._contactAddedId = store.connect( - 'contact-added', - this._onContactAdded.bind(this) - ); - - this._contactRemovedId = store.connect( - 'contact-removed', - this._onContactRemoved.bind(this) - ); - - this._contactChangedId = store.connect( - 'contact-changed', - this._onContactChanged.bind(this) - ); - - // Populate the list - this._populate(); - } - } - - /* - * ContactStore Callbacks - */ - _onContactAdded(store, id) { - const contact = this.store.get_contact(id); - this._addContact(contact); - } - - _onContactRemoved(store, id) { - const rows = this.list.get_children(); - - for (let i = 0, len = rows.length; i < len; i++) { - const row = rows[i]; - - if (row.contact.id === id) { - row.destroy(); - // HACK: temporary mitigator for mysterious GtkListBox leak - system.gc(); - } - } - } - - _onContactChanged(store, id) { - this._onContactRemoved(store, id); - this._onContactAdded(store, id); - } - - _onDestroy(chooser) { - chooser.store = null; - } - - _onSearchChanged(entry) { - this.list._entry = entry.text; - let dynamic = this.list.get_row_at_index(0); - - // If the entry contains string with 2 or more digits... - if (entry.text.replace(/\D/g, '').length >= 2) { - // ...ensure we have a dynamic contact for it - if (!dynamic || !dynamic.__tmp) { - dynamic = new AddressRow({ - // TRANSLATORS: A phone number (eg. "Send to 555-5555") - name: _('Send to %s').format(entry.text), - numbers: [{type: 'unknown', value: entry.text}], - }); - dynamic.__tmp = true; - this.list.add(dynamic); - - // ...or if we already do, then update it - } else { - const address = entry.text; - - // Update contact object - dynamic.contact.name = address; - dynamic.contact.numbers[0].value = address; - - // Update UI - dynamic.name_label.label = _('Send to %s').format(address); - dynamic.address_label.label = address; - } - - // ...otherwise remove any dynamic contact that's been created - } else if (dynamic && dynamic.__tmp) { - dynamic.destroy(); - } - - this.list.invalidate_filter(); - this.list.invalidate_sort(); - } - - // GtkListBox::row-activated - _onNumberSelected(box, row) { - if (row === null) - return; - - // Emit the number - const address = row.number.value; - this.emit('number-selected', address); - - // Reset the contact list - this.entry.text = ''; - this.list.select_row(null); - this.scrolled.vadjustment.value = 0; - } - - _filter(row) { - // Dynamic contact always shown - if (row.__tmp) - return true; - - const query = row.get_parent()._entry; - - // Show contact if text is substring of name - const queryName = query.toLocaleLowerCase(); - - if (row.contact.name.toLocaleLowerCase().includes(queryName)) - return true; - - // Show contact if text is substring of number - const queryNumber = query.toPhoneNumber(); - - if (queryNumber.length) { - for (const number of row.contact.numbers) { - if (number.value.toPhoneNumber().includes(queryNumber)) - return true; - } - - // Query is effectively empty - } else if (/^0+/.test(query)) { - return true; - } - - return false; - } - - _sort(row1, row2) { - if (row1.__tmp) - return -1; - - if (row2.__tmp) - return 1; - - return row1.contact.name.localeCompare(row2.contact.name); - } - - _populate() { - // Add each contact - const contacts = this.store.contacts; - - for (let i = 0, len = contacts.length; i < len; i++) - this._addContact(contacts[i]); - } - - _addContactNumber(contact, index) { - const row = new AddressRow(contact, index); - this.list.add(row); - - return row; - } - - _addContact(contact) { - try { - // HACK: fix missing contact names - if (contact.name === undefined) - contact.name = _('Unknown Contact'); - - if (contact.numbers.length === 1) - return this._addContactNumber(contact, 0); - - for (let i = 0, len = contact.numbers.length; i < len; i++) - this._addContactNumber(contact, i); - } catch (e) { - logError(e); - } - } - - /** - * Get a dictionary of number-contact pairs for each selected phone number. - * - * @return {Object[]} A dictionary of contacts - */ - getSelected() { - try { - const selected = {}; - - for (const row of this.list.get_selected_rows()) - selected[row.number.value] = row.contact; - - return selected; - } catch (e) { - logError(e); - return {}; - } - } -}); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/legacyMessaging.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/legacyMessaging.js deleted file mode 100755 index bda1ab31..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/legacyMessaging.js +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import * as Contacts from '../ui/contacts.js'; -import * as Messaging from '../ui/messaging.js'; -import * as URI from '../utils/uri.js'; -import '../utils/ui.js'; - - -const Dialog = GObject.registerClass({ - GTypeName: 'GSConnectLegacyMessagingDialog', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The plugin providing messages', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/legacy-messaging-dialog.ui', - Children: [ - 'infobar', 'stack', - 'message-box', 'message-avatar', 'message-label', 'entry', - ], -}, class Dialog extends Gtk.Dialog { - - _init(params) { - super._init({ - application: Gio.Application.get_default(), - device: params.device, - plugin: params.plugin, - use_header_bar: true, - }); - - this.set_response_sensitive(Gtk.ResponseType.OK, false); - - // Dup some functions - this.headerbar = this.get_titlebar(); - this._setHeaderBar = Messaging.Window.prototype._setHeaderBar; - - // Info bar - this.device.bind_property( - 'connected', - this.infobar, - 'reveal-child', - GObject.BindingFlags.INVERT_BOOLEAN - ); - - // Message Entry/Send Button - this.device.bind_property( - 'connected', - this.entry, - 'sensitive', - GObject.BindingFlags.DEFAULT - ); - - this._connectedId = this.device.connect( - 'notify::connected', - this._onStateChanged.bind(this) - ); - - this._entryChangedId = this.entry.buffer.connect( - 'changed', - this._onStateChanged.bind(this) - ); - - // Set the message if given - if (params.message) { - this.message = params.message; - this.addresses = params.message.addresses; - - this.message_avatar.contact = this.device.contacts.query({ - number: this.addresses[0].address, - }); - this.message_label.label = URI.linkify(this.message.body); - this.message_box.visible = true; - - // Otherwise set the address(es) if we were passed those - } else if (params.addresses) { - this.addresses = params.addresses; - } - - // Load the contact list if we weren't supplied with an address - if (this.addresses.length === 0) { - this.contact_chooser = new Contacts.ContactChooser({ - device: this.device, - }); - this.stack.add_named(this.contact_chooser, 'contact-chooser'); - this.stack.child_set_property(this.contact_chooser, 'position', 0); - - this._numberSelectedId = this.contact_chooser.connect( - 'number-selected', - this._onNumberSelected.bind(this) - ); - - this.stack.visible_child_name = 'contact-chooser'; - } - - this.restoreGeometry('legacy-messaging-dialog'); - - this.connect('destroy', this._onDestroy); - } - - _onDestroy(dialog) { - if (dialog._numberSelectedId !== undefined) { - dialog.contact_chooser.disconnect(dialog._numberSelectedId); - dialog.contact_chooser.destroy(); - } - - dialog.entry.buffer.disconnect(dialog._entryChangedId); - dialog.device.disconnect(dialog._connectedId); - } - - vfunc_delete_event() { - this.saveGeometry(); - - return false; - } - - vfunc_response(response_id) { - if (response_id === Gtk.ResponseType.OK) { - // Refuse to send empty or whitespace only texts - if (!this.entry.buffer.text.trim()) - return; - - this.plugin.sendMessage( - this.addresses, - this.entry.buffer.text, - 1, - true - ); - } - - this.destroy(); - } - - get addresses() { - if (this._addresses === undefined) - this._addresses = []; - - return this._addresses; - } - - set addresses(addresses = []) { - this._addresses = addresses; - - // Set the headerbar - this._setHeaderBar(this._addresses); - - // Show the message editor - this.stack.visible_child_name = 'message-editor'; - this._onStateChanged(); - } - - get device() { - if (this._device === undefined) - this._device = null; - - return this._device; - } - - set device(device) { - this._device = device; - } - - get plugin() { - if (this._plugin === undefined) - this._plugin = null; - - return this._plugin; - } - - set plugin(plugin) { - this._plugin = plugin; - } - - _onActivateLink(label, uri) { - Gtk.show_uri_on_window( - this.get_toplevel(), - uri.includes('://') ? uri : `https://${uri}`, - Gtk.get_current_event_time() - ); - - return true; - } - - _onNumberSelected(chooser, number) { - const contacts = chooser.getSelected(); - - this.addresses = Object.keys(contacts).map(address => { - return {address: address}; - }); - } - - _onStateChanged() { - if (this.device.connected && - this.entry.buffer.text.trim() && - this.stack.visible_child_name === 'message-editor') - this.set_response_sensitive(Gtk.ResponseType.OK, true); - else - this.set_response_sensitive(Gtk.ResponseType.OK, false); - } - - /** - * Set the contents of the message entry - * - * @param {string} text - The message to place in the entry - */ - setMessage(text) { - this.entry.buffer.text = text; - } -}); - -export default Dialog; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/messaging.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/messaging.js deleted file mode 100755 index 6f535840..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/messaging.js +++ /dev/null @@ -1,1320 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import Pango from 'gi://Pango'; - -import system from 'system'; - -import * as Contacts from './contacts.js'; -import * as Sms from '../plugins/sms.js'; -import * as URI from '../utils/uri.js'; -import '../utils/ui.js'; - -const Tweener = imports.tweener.tweener; - - -/* - * Useful time constants - */ -const TIME_SPAN_MINUTE = 60000; -const TIME_SPAN_HOUR = 3600000; -const TIME_SPAN_DAY = 86400000; -const TIME_SPAN_WEEK = 604800000; - - -// Less than an hour (eg. 42 minutes ago) -const _lthLong = new Intl.RelativeTimeFormat('default', { - numeric: 'auto', - style: 'long', -}); - -// Less than a day ago (eg. 11:42 PM) -const _ltdFormat = new Intl.DateTimeFormat('default', { - hour: 'numeric', - minute: 'numeric', -}); - -// Less than a week ago (eg. Monday) -const _ltwLong = new Intl.DateTimeFormat('default', { - weekday: 'long', -}); - -// Less than a week ago (eg. Mon) -const _ltwShort = new Intl.DateTimeFormat('default', { - weekday: 'short', -}); - -// Less than a year (eg. Oct 31) -const _ltyShort = new Intl.DateTimeFormat('default', { - day: 'numeric', - month: 'short', -}); - -// Less than a year (eg. October 31) -const _ltyLong = new Intl.DateTimeFormat('default', { - day: 'numeric', - month: 'long', -}); - -// Greater than a year (eg. October 31, 2019) -const _gtyLong = new Intl.DateTimeFormat('default', { - day: 'numeric', - month: 'long', - year: 'numeric', -}); - -// Greater than a year (eg. 10/31/2019) -const _gtyShort = new Intl.DateTimeFormat('default', { - day: 'numeric', - month: 'numeric', - year: 'numeric', -}); - -// Pretty close to strftime's %c -const _cFormat = new Intl.DateTimeFormat('default', { - year: 'numeric', - month: 'short', - day: 'numeric', - weekday: 'short', - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - timeZoneName: 'short', -}); - - -/** - * Return a human-readable timestamp, formatted for longer contexts. - * - * @param {number} time - Milliseconds since the epoch (local time) - * @return {string} A localized timestamp similar to what Android Messages uses - */ -function getTime(time) { - const date = new Date(time); - const now = new Date(); - const diff = now - time; - - // Super recent - if (diff < TIME_SPAN_MINUTE) - // TRANSLATORS: Less than a minute ago - return _('Just now'); - - // Under an hour (TODO: these labels aren't updated) - if (diff < TIME_SPAN_HOUR) - return _lthLong.format(-Math.floor(diff / TIME_SPAN_MINUTE), 'minute'); - - // Yesterday, but less than 24 hours ago - if (diff < TIME_SPAN_DAY && now.getDay() !== date.getDay()) - // TRANSLATORS: Yesterday, but less than 24 hours (eg. Yesterday · 11:29 PM) - return _('Yesterday・%s').format(_ltdFormat.format(time)); - - // Less than a day ago - if (diff < TIME_SPAN_DAY) - return _ltdFormat.format(time); - - // Less than a week ago - if (diff < TIME_SPAN_WEEK) - return _ltwLong.format(time); - - // Sometime this year - if (date.getFullYear() === now.getFullYear()) - return _ltyLong.format(time); - - // Earlier than that - return _gtyLong.format(time); -} - - -/** - * Return a human-readable timestamp, formatted for shorter contexts. - * - * @param {number} time - Milliseconds since the epoch (local time) - * @return {string} A localized timestamp similar to what Android Messages uses - */ -function getShortTime(time) { - const date = new Date(time); - const now = new Date(); - const diff = now - time; - - if (diff < TIME_SPAN_MINUTE) - // TRANSLATORS: Less than a minute ago - return _('Just now'); - - if (diff < TIME_SPAN_HOUR) { - // TRANSLATORS: Time duration in minutes (eg. 15 minutes) - return ngettext( - '%d minute', - '%d minutes', - (diff / TIME_SPAN_MINUTE) - ).format(diff / TIME_SPAN_MINUTE); - } - - // Less than a day ago - if (diff < TIME_SPAN_DAY) - return _ltdFormat.format(time); - - // Less than a week ago - if (diff < TIME_SPAN_WEEK) - return _ltwShort.format(time); - - // Sometime this year - if (date.getFullYear() === now.getFullYear()) - return _ltyShort.format(time); - - // Earlier than that - return _gtyShort.format(time); -} - - -/** - * Return a human-readable timestamp, similar to `strftime()` with `%c`. - * - * @param {number} time - Milliseconds since the epoch (local time) - * @return {string} A localized timestamp - */ -function getDetailedTime(time) { - return _cFormat.format(time); -} - - -function setAvatarVisible(row, visible) { - const incoming = row.message.type === Sms.MessageBox.INBOX; - - // Adjust the margins - if (visible) { - row.grid.margin_start = incoming ? 6 : 56; - row.grid.margin_bottom = 6; - } else { - row.grid.margin_start = incoming ? 44 : 56; - row.grid.margin_bottom = 0; - } - - // Show hide the avatar - if (incoming) - row.avatar.visible = visible; -} - - -/** - * A ListBoxRow for a preview of a conversation - */ -const ConversationMessage = GObject.registerClass({ - GTypeName: 'GSConnectMessagingConversationMessage', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/messaging-conversation-message.ui', - Children: ['grid', 'avatar', 'sender-label', 'message-label'], -}, class ConversationMessage extends Gtk.ListBoxRow { - _init(contact, message) { - super._init(); - - this.contact = contact; - this.message = message; - - // Sort properties - this.sender = message.addresses[0].address || 'unknown'; - this.message_label.label = URI.linkify(message.body); - this.message_label.tooltip_text = getDetailedTime(message.date); - - // Add avatar for incoming messages - if (message.type === Sms.MessageBox.INBOX) { - this.grid.margin_end = 18; - this.grid.halign = Gtk.Align.START; - - this.avatar.contact = this.contact; - this.avatar.visible = true; - - this.sender_label.label = contact.name; - this.sender_label.visible = true; - - this.message_label.get_style_context().add_class('message-in'); - this.message_label.halign = Gtk.Align.START; - } else { - this.message_label.get_style_context().add_class('message-out'); - } - } - - _onActivateLink(label, uri) { - Gtk.show_uri_on_window( - this.get_toplevel(), - uri.includes('://') ? uri : `https://${uri}`, - Gtk.get_current_event_time() - ); - - return true; - } - - get date() { - return this._message.date; - } - - get thread_id() { - return this._message.thread_id; - } - - get message() { - if (this._message === undefined) - this._message = null; - - return this._message; - } - - set message(message) { - this._message = message; - } -}); - - -/** - * A widget for displaying a conversation thread, with an entry for responding. - */ -const Conversation = GObject.registerClass({ - GTypeName: 'GSConnectMessagingConversation', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this conversation', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The plugin providing this conversation', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'has-pending': GObject.ParamSpec.boolean( - 'has-pending', - 'Has Pending', - 'Whether there are sent messages pending confirmation', - GObject.ParamFlags.READABLE, - false - ), - 'thread-id': GObject.ParamSpec.string( - 'thread-id', - 'Thread ID', - 'The current thread', - GObject.ParamFlags.READWRITE, - '' - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/messaging-conversation.ui', - Children: [ - 'entry', 'list', 'scrolled', - 'pending', 'pending-box', - ], -}, class MessagingConversation extends Gtk.Grid { - - _init(params) { - super._init({ - device: params.device, - plugin: params.plugin, - }); - Object.assign(this, params); - - this.device.bind_property( - 'connected', - this.entry, - 'sensitive', - GObject.BindingFlags.SYNC_CREATE - ); - - // If we're disconnected pending messages might not succeed, but we'll - // leave them until reconnect when we'll ask for an update - this._connectedId = this.device.connect( - 'notify::connected', - this._onConnected.bind(this) - ); - - // Pending messages - this.pending.message = { - date: Number.MAX_SAFE_INTEGER, - type: Sms.MessageBox.OUTBOX, - }; - - // Auto-scrolling - this._vadj = this.scrolled.get_vadjustment(); - this._scrolledId = this._vadj.connect( - 'value-changed', - this._holdPosition.bind(this) - ); - - // Message List - this.list.set_header_func(this._headerMessages); - this.list.set_sort_func(this._sortMessages); - this._populateMessages(); - - // Cleanup on ::destroy - this.connect('destroy', this._onDestroy); - } - - get addresses() { - if (this._addresses === undefined) - this._addresses = []; - - return this._addresses; - } - - set addresses(addresses) { - if (!addresses || addresses.length === 0) { - this._addresses = []; - this._contacts = {}; - return; - } - - // Lookup a contact for each address object, then loop back to correct - // each address carried by the message. - this._addresses = addresses; - - for (let i = 0, len = this.addresses.length; i < len; i++) { - // Lookup the contact - const address = this.addresses[i].address; - const contact = this.device.contacts.query({number: address}); - - // Get corrected address - let number = address.toPhoneNumber(); - - if (!number) - continue; - - for (const contactNumber of contact.numbers) { - const cnumber = contactNumber.value.toPhoneNumber(); - - if (cnumber && (number.endsWith(cnumber) || cnumber.endsWith(number))) { - number = contactNumber.value; - break; - } - } - - // Store the final result - this.addresses[i].address = number; - this.contacts[address] = contact; - } - - // TODO: Mark the entry as insensitive for group messages - if (this.addresses.length > 1) { - this.entry.placeholder_text = _('Not available'); - this.entry.secondary_icon_name = null; - this.entry.secondary_icon_tooltip_text = null; - this.entry.sensitive = false; - this.entry.tooltip_text = null; - } - } - - get contacts() { - if (this._contacts === undefined) - this._contacts = {}; - - return this._contacts; - } - - get has_pending() { - if (this.pending_box === undefined) - return false; - - return (this.pending_box.get_children().length > 0); - } - - get plugin() { - if (this._plugin === undefined) - this._plugin = null; - - return this._plugin; - } - - set plugin(plugin) { - this._plugin = plugin; - } - - get thread_id() { - if (this._thread_id === undefined) - this._thread_id = null; - - return this._thread_id; - } - - set thread_id(thread_id) { - const thread = this.plugin.threads[thread_id]; - const message = (thread) ? thread[0] : null; - - if (message && this.addresses.length === 0) { - this.addresses = message.addresses; - this._thread_id = thread_id; - } - } - - _onConnected(device) { - if (device.connected) - this.pending_box.foreach(msg => msg.destroy()); - } - - _onDestroy(conversation) { - conversation.device.disconnect(conversation._connectedId); - conversation._vadj.disconnect(conversation._scrolledId); - - conversation.list.foreach(message => { - // HACK: temporary mitigator for mysterious GtkListBox leak - message.destroy(); - system.gc(); - }); - } - - _onEdgeReached(scrolled_window, pos) { - // Try to load more messages - if (pos === Gtk.PositionType.TOP) - this.logPrevious(); - - // Release any hold to resume auto-scrolling - else if (pos === Gtk.PositionType.BOTTOM) - this._releasePosition(); - } - - _onEntryChanged(entry) { - entry.secondary_icon_sensitive = (entry.text.length); - } - - _onKeyPressEvent(entry, event) { - const keyval = event.get_keyval()[1]; - const state = event.get_state()[1]; - const mask = state & Gtk.accelerator_get_default_mod_mask(); - - if (keyval === Gdk.KEY_Return && (mask & Gdk.ModifierType.SHIFT_MASK)) { - entry.emit('insert-at-cursor', '\n'); - return true; - } - - return false; - } - - _onSendMessage(entry, signal_id, event) { - // Don't send empty texts - if (!this.entry.text.trim()) - return; - - // Send the message - this.plugin.sendMessage(this.addresses, this.entry.text); - - // Add a phony message in the pending box - const message = new Gtk.Label({ - label: URI.linkify(this.entry.text), - halign: Gtk.Align.END, - selectable: true, - use_markup: true, - visible: true, - wrap: true, - wrap_mode: Pango.WrapMode.WORD_CHAR, - xalign: 0, - }); - message.get_style_context().add_class('message-out'); - message.date = Date.now(); - message.type = Sms.MessageBox.SENT; - - // Notify to reveal the pending box - this.pending_box.add(message); - this.notify('has-pending'); - - // Clear the entry - this.entry.text = ''; - } - - _onSizeAllocate(listbox, allocation) { - const upper = this._vadj.get_upper(); - const pageSize = this._vadj.get_page_size(); - - // If the scrolled window hasn't been filled yet, load another message - if (upper <= pageSize) { - this.logPrevious(); - this.scrolled.get_child().check_resize(); - - // We've been asked to hold the position, so we'll reset the adjustment - // value and update the hold position - } else if (this.__pos) { - this._vadj.set_value(upper - this.__pos); - - // Otherwise we probably appended a message and should scroll to it - } else { - this._scrollPosition(Gtk.PositionType.BOTTOM); - } - } - - /** - * Create a message row, ensuring a contact object has been retrieved or - * generated for the message. - * - * @param {Object} message - A dictionary of message data - * @return {ConversationMessage} A message row - */ - _createMessageRow(message) { - // Ensure we have a contact - const sender = message.addresses[0].address || 'unknown'; - - if (this.contacts[sender] === undefined) { - this.contacts[sender] = this.device.contacts.query({ - number: sender, - }); - } - - return new ConversationMessage(this.contacts[sender], message); - } - - _populateMessages() { - this.__first = null; - this.__last = null; - this.__pos = 0; - this.__messages = []; - - // Try and find a thread_id for this number - if (this.thread_id === null && this.addresses.length) - this._thread_id = this.plugin.getThreadIdForAddresses(this.addresses); - - // Make a copy of the thread and fill the window with messages - if (this.plugin.threads[this.thread_id]) { - this.__messages = this.plugin.threads[this.thread_id].slice(0); - this.logPrevious(); - } - } - - _headerMessages(row, before) { - // Skip pending - if (row.get_name() === 'pending') - return; - - if (before === null) - return setAvatarVisible(row, true); - - // Add date header if the last message was more than an hour ago - let header = row.get_header(); - - if ((row.message.date - before.message.date) > TIME_SPAN_HOUR) { - if (!header) { - header = new Gtk.Label({visible: true, selectable: true}); - header.get_style_context().add_class('dim-label'); - row.set_header(header); - } - - header.label = getTime(row.message.date); - - // Also show the avatar - setAvatarVisible(row, true); - - row.sender_label.visible = row.message.addresses.length > 1; - - // Or if the previous sender was the same, hide its avatar - } else if (row.message.type === before.message.type && - row.sender.equalsPhoneNumber(before.sender)) { - setAvatarVisible(before, false); - setAvatarVisible(row, true); - - row.sender_label.visible = false; - - // otherwise show the avatar - } else { - setAvatarVisible(row, true); - } - } - - _holdPosition() { - this.__pos = this._vadj.get_upper() - this._vadj.get_value(); - } - - _releasePosition() { - this.__pos = 0; - } - - _scrollPosition(pos = Gtk.PositionType.BOTTOM, animate = true) { - let vpos = pos; - this._vadj.freeze_notify(); - - if (pos === Gtk.PositionType.BOTTOM) - vpos = this._vadj.get_upper() - this._vadj.get_page_size(); - - if (animate) { - Tweener.addTween(this._vadj, { - value: vpos, - time: 0.5, - transition: 'easeInOutCubic', - onComplete: () => this._vadj.thaw_notify(), - }); - } else { - GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - this._vadj.set_value(vpos); - this._vadj.thaw_notify(); - }); - } - } - - _sortMessages(row1, row2) { - return (row1.message.date > row2.message.date) ? 1 : -1; - } - - /** - * Log the next message in the conversation. - * - * @param {Object} message - A message object - */ - logNext(message) { - try { - // TODO: Unsupported MessageBox - if (message.type !== Sms.MessageBox.INBOX && - message.type !== Sms.MessageBox.SENT) - throw TypeError(`invalid message box ${message.type}`); - - // Append the message - const row = this._createMessageRow(message); - this.list.add(row); - this.list.invalidate_headers(); - - // Remove the first pending message - if (this.has_pending && message.type === Sms.MessageBox.SENT) { - this.pending_box.get_children()[0].destroy(); - this.notify('has-pending'); - } - } catch (e) { - debug(e); - } - } - - /** - * Log the previous message in the thread - */ - logPrevious() { - try { - const message = this.__messages.pop(); - - if (!message) - return; - - // TODO: Unsupported MessageBox - if (message.type !== Sms.MessageBox.INBOX && - message.type !== Sms.MessageBox.SENT) - throw TypeError(`invalid message box ${message.type}`); - - // Prepend the message - const row = this._createMessageRow(message); - this.list.prepend(row); - this.list.invalidate_headers(); - } catch (e) { - debug(e); - } - } - - /** - * Set the contents of the message entry - * - * @param {string} text - The message to place in the entry - */ - setMessage(text) { - this.entry.text = text; - this.entry.emit('move-cursor', 0, text.length, false); - } -}); - - -/** - * A ListBoxRow for a preview of a conversation - */ -const ConversationSummary = GObject.registerClass({ - GTypeName: 'GSConnectMessagingConversationSummary', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/messaging-conversation-summary.ui', - Children: ['avatar', 'name-label', 'time-label', 'body-label'], -}, class ConversationSummary extends Gtk.ListBoxRow { - _init(contacts, message) { - super._init(); - - this.contacts = contacts; - this.message = message; - } - - get date() { - return this._message.date; - } - - get thread_id() { - return this._message.thread_id; - } - - get message() { - return this._message; - } - - set message(message) { - this._message = message; - this._sender = message.addresses[0].address || 'unknown'; - - // Contact Name - let nameLabel = _('Unknown Contact'); - - // Update avatar for single-recipient messages - if (message.addresses.length === 1) { - this.avatar.contact = this.contacts[this._sender]; - nameLabel = GLib.markup_escape_text(this.avatar.contact.name, -1); - } else { - this.avatar.contact = null; - nameLabel = _('Group Message'); - const participants = []; - message.addresses.forEach((address) => { - participants.push(this.contacts[address.address].name); - }); - this.name_label.tooltip_text = participants.join(', '); - } - - // Contact Name & Message body - let bodyLabel = message.body.split(/\r|\n/)[0]; - bodyLabel = GLib.markup_escape_text(bodyLabel, -1); - - // Ignore the 'read' flag if it's an outgoing message - if (message.type === Sms.MessageBox.SENT) { - // TRANSLATORS: An outgoing message body in a conversation summary - bodyLabel = _('You: %s').format(bodyLabel); - - // Otherwise make it bold if it's unread - } else if (message.read === Sms.MessageStatus.UNREAD) { - nameLabel = `<b>${nameLabel}</b>`; - bodyLabel = `<b>${bodyLabel}</b>`; - } - - // Set the labels, body always smaller - this.name_label.label = nameLabel; - this.body_label.label = `<small>${bodyLabel}</small>`; - - // Time - const timeLabel = `<small>${getShortTime(message.date)}</small>`; - this.time_label.label = timeLabel; - } - - /** - * Update the relative time label. - */ - update() { - const timeLabel = `<small>${getShortTime(this.message.date)}</small>`; - this.time_label.label = timeLabel; - } -}); - - -/** - * A Gtk.ApplicationWindow for SMS conversations - */ -export const Window = GObject.registerClass({ - GTypeName: 'GSConnectMessagingWindow', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The plugin providing messages', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'thread-id': GObject.ParamSpec.string( - 'thread-id', - 'Thread ID', - 'The current thread', - GObject.ParamFlags.READWRITE, - '' - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/messaging-window.ui', - Children: [ - 'headerbar', 'infobar', - 'thread-list', 'stack', - ], -}, class MessagingWindow extends Gtk.ApplicationWindow { - - _init(params) { - super._init(params); - this.headerbar.subtitle = this.device.name; - - this.insert_action_group('device', this.device); - - // Device Status - this.device.bind_property( - 'connected', - this.infobar, - 'reveal-child', - GObject.BindingFlags.INVERT_BOOLEAN - ); - - // Contacts - this.contact_chooser = new Contacts.ContactChooser({ - device: this.device, - }); - this.stack.add_named(this.contact_chooser, 'contact-chooser'); - - this._numberSelectedId = this.contact_chooser.connect( - 'number-selected', - this._onNumberSelected.bind(this) - ); - - // Threads - this.thread_list.set_sort_func(this._sortThreads); - - this._threadsChangedId = this.plugin.connect( - 'notify::threads', - this._onThreadsChanged.bind(this) - ); - - this._timestampThreadsId = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT_IDLE, - 60, - this._timestampThreads.bind(this) - ); - - this._sync(); - this._onThreadsChanged(); - this.restoreGeometry('messaging'); - } - - vfunc_delete_event(event) { - this.saveGeometry(); - - GLib.source_remove(this._timestampThreadsId); - this.contact_chooser.disconnect(this._numberSelectedId); - this.plugin.disconnect(this._threadsChangedId); - - return false; - } - - get plugin() { - return this._plugin || null; - } - - set plugin(plugin) { - this._plugin = plugin; - } - - get thread_id() { - return this.stack.visible_child_name; - } - - set thread_id(thread_id) { - thread_id = `${thread_id}`; // FIXME - - // Reset to the empty placeholder - if (!thread_id) { - this.thread_list.select_row(null); - this.stack.set_visible_child_name('placeholder'); - return; - } - - // Create a conversation widget if there isn't one - let conversation = this.stack.get_child_by_name(thread_id); - const thread = this.plugin.threads[thread_id]; - - if (conversation === null) { - if (!thread) { - debug(`Thread ID ${thread_id} not found`); - return; - } - - conversation = new Conversation({ - device: this.device, - plugin: this.plugin, - thread_id: thread_id, - }); - - this.stack.add_named(conversation, thread_id); - } - - // Figure out whether this is a multi-recipient thread - this._setHeaderBar(thread[0].addresses); - - // Select the conversation and entry active - this.stack.visible_child = conversation; - this.stack.visible_child.entry.has_focus = true; - - // There was a pending message waiting for a conversation to be chosen - if (this._pendingShare) { - conversation.setMessage(this._pendingShare); - this._pendingShare = null; - } - - this._thread_id = thread_id; - this.notify('thread_id'); - } - - _setHeaderBar(addresses = []) { - const address = addresses[0].address; - const contact = this.device.contacts.query({number: address}); - - if (addresses.length === 1) { - this.headerbar.title = contact.name; - this.headerbar.subtitle = Contacts.getDisplayNumber(contact, address); - } else { - const otherLength = addresses.length - 1; - - this.headerbar.title = contact.name; - this.headerbar.subtitle = ngettext( - 'And %d other contact', - 'And %d others', - otherLength - ).format(otherLength); - } - } - - _sync() { - this.device.contacts.fetch(); - this.plugin.connected(); - } - - _onNewConversation() { - this._sync(); - this.stack.set_visible_child_name('contact-chooser'); - this.thread_list.select_row(null); - this.contact_chooser.entry.has_focus = true; - } - - _onNumberSelected(chooser, number) { - const contacts = chooser.getSelected(); - const row = this._getRowForContacts(contacts); - - if (row) - row.emit('activate'); - else - this.setContacts(contacts); - } - - /** - * Threads - */ - _onThreadsChanged() { - // Get the last message in each thread - const messages = {}; - - for (const [thread_id, thread] of Object.entries(this.plugin.threads)) { - const message = thread[thread.length - 1]; - - // Skip messages without a body (eg. MMS messages without text) - if (message.body) - messages[thread_id] = thread[thread.length - 1]; - } - - // Update existing summaries and destroy old ones - for (const row of this.thread_list.get_children()) { - const message = messages[row.thread_id]; - - // If it's an existing conversation, update it - if (message) { - // Ensure there's a contact mapping - const sender = message.addresses[0].address || 'unknown'; - - if (row.contacts[sender] === undefined) { - row.contacts[sender] = this.device.contacts.query({ - number: sender, - }); - } - - row.message = message; - delete messages[row.thread_id]; - - // Otherwise destroy it - } else { - // Destroy the conversation widget - const conversation = this.stack.get_child_by_name(`${row.thread_id}`); - - if (conversation) { - conversation.destroy(); - system.gc(); - } - - // Then the summary widget - row.destroy(); - // HACK: temporary mitigator for mysterious GtkListBox leak - system.gc(); - } - } - - // What's left in the dictionary is new summaries - for (const message of Object.values(messages)) { - const contacts = this.device.contacts.lookupAddresses(message.addresses); - const conversation = new ConversationSummary(contacts, message); - this.thread_list.add(conversation); - } - - // Re-sort the summaries - this.thread_list.invalidate_sort(); - } - - // GtkListBox::row-activated - _onThreadSelected(box, row) { - // Show the conversation for this number (if applicable) - if (row) { - this.thread_id = row.thread_id; - - // Show the placeholder - } else { - this.headerbar.title = _('Messaging'); - this.headerbar.subtitle = this.device.name; - } - } - - _sortThreads(row1, row2) { - return (row1.date > row2.date) ? -1 : 1; - } - - _timestampThreads() { - if (this.visible) - this.thread_list.foreach(row => row.update()); - - return GLib.SOURCE_CONTINUE; - } - - /** - * Find the thread row for @contacts - * - * @param {Object[]} contacts - A contact group - * @return {ConversationSummary|null} The thread row or %null - */ - _getRowForContacts(contacts) { - const addresses = Object.keys(contacts).map(address => { - return {address: address}; - }); - - // Try to find a thread_id - const thread_id = this.plugin.getThreadIdForAddresses(addresses); - - for (const row of this.thread_list.get_children()) { - if (row.message.thread_id === thread_id) - return row; - } - - return null; - } - - setContacts(contacts) { - // Group the addresses - const addresses = []; - - for (const address of Object.keys(contacts)) - addresses.push({address: address}); - - // Try to find a thread ID for this address group - let thread_id = this.plugin.getThreadIdForAddresses(addresses); - - if (thread_id === null) - thread_id = GLib.uuid_string_random(); - else - thread_id = thread_id.toString(); - - // Try to find a thread row for the ID - const row = this._getRowForContacts(contacts); - - if (row !== null) { - this.thread_list.select_row(row); - return; - } - - // We're creating a new conversation - const conversation = new Conversation({ - device: this.device, - plugin: this.plugin, - addresses: addresses, - }); - - // Set the headerbar - this._setHeaderBar(addresses); - - // Select the conversation and entry active - this.stack.add_named(conversation, thread_id); - this.stack.visible_child = conversation; - this.stack.visible_child.entry.has_focus = true; - - // There was a pending message waiting for a conversation to be chosen - if (this._pendingShare) { - conversation.setMessage(this._pendingShare); - this._pendingShare = null; - } - - this._thread_id = thread_id; - this.notify('thread-id'); - } - - _includesAddress(addresses, addressObj) { - const number = addressObj.address.toPhoneNumber(); - - for (const haystackObj of addresses) { - const tnumber = haystackObj.address.toPhoneNumber(); - - if (number.endsWith(tnumber) || tnumber.endsWith(number)) - return true; - } - - return false; - } - - /** - * Try and find an existing conversation widget for @message. - * - * @param {Object} message - A message object - * @return {Conversation|null} A conversation widget or %null - */ - getConversationForMessage(message) { - // TODO: This shouldn't happen? - if (message === null) - return null; - - // First try to find a conversation by thread_id - const thread_id = `${message.thread_id}`; - const conversation = this.stack.get_child_by_name(thread_id); - - if (conversation !== null) - return conversation; - - // Try and find one by matching addresses, which is necessary if we've - // started a thread locally and haven't set the thread_id - const addresses = message.addresses; - - for (const conversation of this.stack.get_children()) { - if (conversation.addresses === undefined || - conversation.addresses.length !== addresses.length) - continue; - - const caddrs = conversation.addresses; - - // If we find a match, set `thread-id` on the conversation and the - // child property `name`. - if (addresses.every(addr => this._includesAddress(caddrs, addr))) { - conversation._thread_id = thread_id; - this.stack.child_set_property(conversation, 'name', thread_id); - - return conversation; - } - } - - return null; - } - - /** - * Set the contents of the message entry. If @pending is %false set the - * message of the currently selected conversation, otherwise mark the - * message to be set for the next selected conversation. - * - * @param {string} message - The message to place in the entry - * @param {boolean} pending - Wait for a conversation to be selected - */ - setMessage(message, pending = false) { - try { - if (pending) - this._pendingShare = message; - else - this.stack.visible_child.setMessage(message); - } catch (e) { - debug(e); - } - } -}); - - -/** - * A Gtk.ApplicationWindow for selecting from open conversations - */ -export const ConversationChooser = GObject.registerClass({ - GTypeName: 'GSConnectConversationChooser', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'message': GObject.ParamSpec.string( - 'message', - 'Message', - 'The message to share', - GObject.ParamFlags.READWRITE, - '' - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The plugin providing messages', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - }, -}, class ConversationChooser extends Gtk.ApplicationWindow { - - _init(params) { - super._init(Object.assign({ - title: _('Share Link'), - default_width: 300, - default_height: 200, - }, params)); - this.set_keep_above(true); - - // HeaderBar - this.headerbar = new Gtk.HeaderBar({ - title: _('Share Link'), - subtitle: this.message, - show_close_button: true, - tooltip_text: this.message, - }); - this.set_titlebar(this.headerbar); - - const newButton = new Gtk.Button({ - image: new Gtk.Image({icon_name: 'list-add-symbolic'}), - tooltip_text: _('New Conversation'), - always_show_image: true, - }); - newButton.connect('clicked', this._new.bind(this)); - this.headerbar.pack_start(newButton); - - // Threads - const scrolledWindow = new Gtk.ScrolledWindow({ - can_focus: false, - hexpand: true, - vexpand: true, - hscrollbar_policy: Gtk.PolicyType.NEVER, - }); - this.add(scrolledWindow); - - this.thread_list = new Gtk.ListBox({ - activate_on_single_click: false, - }); - this.thread_list.set_sort_func(Window.prototype._sortThreads); - this.thread_list.connect('row-activated', this._select.bind(this)); - scrolledWindow.add(this.thread_list); - - // Filter Setup - Window.prototype._onThreadsChanged.call(this); - this.show_all(); - } - - get plugin() { - return this._plugin || null; - } - - set plugin(plugin) { - this._plugin = plugin; - } - - _new(button) { - const message = this.message; - this.destroy(); - - this.plugin.sms(); - this.plugin.window._onNewConversation(); - this.plugin.window._pendingShare = message; - } - - _select(box, row) { - this.plugin.sms(); - this.plugin.window.thread_id = row.message.thread_id.toString(); - this.plugin.window.setMessage(this.message); - - this.destroy(); - } -}); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/mousepad.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/mousepad.js deleted file mode 100755 index 5c28603f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/mousepad.js +++ /dev/null @@ -1,460 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GLib from 'gi://GLib'; -import Gdk from 'gi://Gdk'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - - -/** - * A map of Gdk to "KDE Connect" keyvals - */ -const ReverseKeyMap = new Map([ - [Gdk.KEY_BackSpace, 1], - [Gdk.KEY_Tab, 2], - [Gdk.KEY_Linefeed, 3], - [Gdk.KEY_Left, 4], - [Gdk.KEY_Up, 5], - [Gdk.KEY_Right, 6], - [Gdk.KEY_Down, 7], - [Gdk.KEY_Page_Up, 8], - [Gdk.KEY_Page_Down, 9], - [Gdk.KEY_Home, 10], - [Gdk.KEY_End, 11], - [Gdk.KEY_Return, 12], - [Gdk.KEY_Delete, 13], - [Gdk.KEY_Escape, 14], - [Gdk.KEY_Sys_Req, 15], - [Gdk.KEY_Scroll_Lock, 16], - [Gdk.KEY_F1, 21], - [Gdk.KEY_F2, 22], - [Gdk.KEY_F3, 23], - [Gdk.KEY_F4, 24], - [Gdk.KEY_F5, 25], - [Gdk.KEY_F6, 26], - [Gdk.KEY_F7, 27], - [Gdk.KEY_F8, 28], - [Gdk.KEY_F9, 29], - [Gdk.KEY_F10, 30], - [Gdk.KEY_F11, 31], - [Gdk.KEY_F12, 32], -]); - - -/* - * A list of keyvals we consider modifiers - */ -const MOD_KEYS = [ - Gdk.KEY_Alt_L, - Gdk.KEY_Alt_R, - Gdk.KEY_Caps_Lock, - Gdk.KEY_Control_L, - Gdk.KEY_Control_R, - Gdk.KEY_Meta_L, - Gdk.KEY_Meta_R, - Gdk.KEY_Num_Lock, - Gdk.KEY_Shift_L, - Gdk.KEY_Shift_R, - Gdk.KEY_Super_L, - Gdk.KEY_Super_R, -]; - - -/* - * Some convenience functions for checking keyvals for modifiers - */ -const isAlt = (key) => [Gdk.KEY_Alt_L, Gdk.KEY_Alt_R].includes(key); -const isCtrl = (key) => [Gdk.KEY_Control_L, Gdk.KEY_Control_R].includes(key); -const isShift = (key) => [Gdk.KEY_Shift_L, Gdk.KEY_Shift_R].includes(key); -const isSuper = (key) => [Gdk.KEY_Super_L, Gdk.KEY_Super_R].includes(key); - - -export const InputDialog = GObject.registerClass({ - GTypeName: 'GSConnectMousepadInputDialog', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The mousepad plugin associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/mousepad-input-dialog.ui', - Children: [ - 'infobar', 'infobar-label', - 'touchpad-eventbox', 'mouse-left-button', 'mouse-middle-button', 'mouse-right-button', - 'touchpad-drag', 'touchpad-long-press', - 'shift-label', 'ctrl-label', 'alt-label', 'super-label', 'entry', - ], -}, class InputDialog extends Gtk.Dialog { - - _init(params) { - super._init(Object.assign({ - use_header_bar: true, - }, params)); - - const headerbar = this.get_titlebar(); - headerbar.title = _('Remote Input'); - headerbar.subtitle = this.device.name; - - // Main Box - const content = this.get_content_area(); - content.border_width = 0; - - // TRANSLATORS: Displayed when the remote keyboard is not ready to accept input - this.infobar_label.label = _('Remote keyboard on %s is not active').format(this.device.name); - - // Text Input - this.entry.buffer.connect( - 'insert-text', - this._onInsertText.bind(this) - ); - - this.infobar.connect('notify::reveal-child', this._onState.bind(this)); - this.plugin.bind_property('state', this.infobar, 'reveal-child', 6); - - // Mouse Pad - this._resetTouchpadMotion(); - this.touchpad_motion_timeout_id = 0; - this.touchpad_holding = false; - - // Scroll Input - this.add_events(Gdk.EventMask.SCROLL_MASK); - - this.show_all(); - } - - vfunc_delete_event(event) { - this._ungrab(); - return this.hide_on_delete(); - } - - vfunc_grab_broken_event(event) { - if (event.keyboard) - this._ungrab(); - - return false; - } - - vfunc_key_release_event(event) { - if (!this.plugin.state) - debug('ignoring remote keyboard state'); - - const keyvalLower = Gdk.keyval_to_lower(event.keyval); - const realMask = event.state & Gtk.accelerator_get_default_mod_mask(); - - this.alt_label.sensitive = !isAlt(keyvalLower) && (realMask & Gdk.ModifierType.MOD1_MASK); - this.ctrl_label.sensitive = !isCtrl(keyvalLower) && (realMask & Gdk.ModifierType.CONTROL_MASK); - this.shift_label.sensitive = !isShift(keyvalLower) && (realMask & Gdk.ModifierType.SHIFT_MASK); - this.super_label.sensitive = !isSuper(keyvalLower) && (realMask & Gdk.ModifierType.SUPER_MASK); - - return super.vfunc_key_release_event(event); - } - - vfunc_key_press_event(event) { - if (!this.plugin.state) - debug('ignoring remote keyboard state'); - - let keyvalLower = Gdk.keyval_to_lower(event.keyval); - let realMask = event.state & Gtk.accelerator_get_default_mod_mask(); - - this.alt_label.sensitive = isAlt(keyvalLower) || (realMask & Gdk.ModifierType.MOD1_MASK); - this.ctrl_label.sensitive = isCtrl(keyvalLower) || (realMask & Gdk.ModifierType.CONTROL_MASK); - this.shift_label.sensitive = isShift(keyvalLower) || (realMask & Gdk.ModifierType.SHIFT_MASK); - this.super_label.sensitive = isSuper(keyvalLower) || (realMask & Gdk.ModifierType.SUPER_MASK); - - // Wait for a real key before sending - if (MOD_KEYS.includes(keyvalLower)) - return false; - - // Normalize Tab - if (keyvalLower === Gdk.KEY_ISO_Left_Tab) - keyvalLower = Gdk.KEY_Tab; - - // Put shift back if it changed the case of the key, not otherwise. - if (keyvalLower !== event.keyval) - realMask |= Gdk.ModifierType.SHIFT_MASK; - - // HACK: we don't want to use SysRq as a keybinding (but we do want - // Alt+Print), so we avoid translation from Alt+Print to SysRq - if (keyvalLower === Gdk.KEY_Sys_Req && (realMask & Gdk.ModifierType.MOD1_MASK) !== 0) - keyvalLower = Gdk.KEY_Print; - - // CapsLock isn't supported as a keybinding modifier, so keep it from - // confusing us - realMask &= ~Gdk.ModifierType.LOCK_MASK; - - if (keyvalLower === 0) - return false; - - debug(`keyval: ${event.keyval}, mask: ${realMask}`); - - const request = { - alt: !!(realMask & Gdk.ModifierType.MOD1_MASK), - ctrl: !!(realMask & Gdk.ModifierType.CONTROL_MASK), - shift: !!(realMask & Gdk.ModifierType.SHIFT_MASK), - super: !!(realMask & Gdk.ModifierType.SUPER_MASK), - sendAck: true, - }; - - // specialKey - if (ReverseKeyMap.has(event.keyval)) { - request.specialKey = ReverseKeyMap.get(event.keyval); - - // key - } else { - const codePoint = Gdk.keyval_to_unicode(event.keyval); - request.key = String.fromCodePoint(codePoint); - } - - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: request, - }); - - // Pass these key combinations rather than using the echo reply - if (request.alt || request.ctrl || request.super) - return super.vfunc_key_press_event(event); - - return false; - } - - vfunc_scroll_event(event) { - if (event.delta_x === 0 && event.delta_y === 0) - return true; - - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - scroll: true, - dx: event.delta_x * 200, - dy: event.delta_y * 200, - }, - }); - return true; - } - - vfunc_window_state_event(event) { - if (!this.plugin.state) - debug('ignoring remote keyboard state'); - - if (event.new_window_state & Gdk.WindowState.FOCUSED) - this._grab(); - else - this._ungrab(); - - return super.vfunc_window_state_event(event); - } - - _onInsertText(buffer, location, text, len) { - if (this._isAck) - return; - - debug(`insert-text: ${text} (chars ${[...text].length})`); - - for (const char of [...text]) { - if (!char) - continue; - - // TODO: modifiers? - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - alt: false, - ctrl: false, - shift: false, - super: false, - sendAck: false, - key: char, - }, - }); - } - } - - _onState(widget) { - if (!this.plugin.state) - debug('ignoring remote keyboard state'); - - if (this.is_active) - this._grab(); - else - this._ungrab(); - } - - _grab() { - if (!this.visible || this._keyboard) - return; - - const seat = Gdk.Display.get_default().get_default_seat(); - const status = seat.grab( - this.get_window(), - Gdk.SeatCapabilities.KEYBOARD, - false, - null, - null, - null - ); - - if (status !== Gdk.GrabStatus.SUCCESS) { - logError(new Error('Grabbing keyboard failed')); - return; - } - - this._keyboard = seat.get_keyboard(); - this.grab_add(); - this.entry.has_focus = true; - } - - _ungrab() { - if (this._keyboard) { - this._keyboard.get_seat().ungrab(); - this._keyboard = null; - this.grab_remove(); - } - - this.entry.buffer.text = ''; - } - - _resetTouchpadMotion() { - this.touchpad_motion_prev_x = 0; - this.touchpad_motion_prev_y = 0; - this.touchpad_motion_x = 0; - this.touchpad_motion_y = 0; - } - - _onMouseLeftButtonClicked(button) { - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - singleclick: true, - }, - }); - } - - _onMouseMiddleButtonClicked(button) { - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - middleclick: true, - }, - }); - } - - _onMouseRightButtonClicked(button) { - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - rightclick: true, - }, - }); - } - - _onTouchpadDragBegin(gesture) { - this._resetTouchpadMotion(); - - this.touchpad_motion_timeout_id = - GLib.timeout_add(GLib.PRIORITY_DEFAULT, 10, - this._onTouchpadMotionTimeout.bind(this)); - } - - _onTouchpadDragUpdate(gesture, offset_x, offset_y) { - this.touchpad_motion_x = offset_x; - this.touchpad_motion_y = offset_y; - } - - _onTouchpadDragEnd(gesture) { - this._resetTouchpadMotion(); - - GLib.Source.remove(this.touchpad_motion_timeout_id); - this.touchpad_motion_timeout_id = 0; - } - - _onTouchpadLongPressCancelled(gesture) { - const gesture_button = gesture.get_current_button(); - - // Check user dragged less than certain distances. - const is_click = - (Math.abs(this.touchpad_motion_x) < 4) && - (Math.abs(this.touchpad_motion_y) < 4); - - if (is_click) { - const click_body = {}; - switch (gesture_button) { - case 1: - click_body.singleclick = true; - break; - - case 2: - click_body.middleclick = true; - break; - - case 3: - click_body.rightclick = true; - break; - - default: - return; - } - - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: click_body, - }); - } - } - - _onTouchpadLongPressPressed(gesture) { - const gesture_button = gesture.get_current_button(); - - if (gesture_button !== 1) { - debug('Long press on other type of buttons are not handled.'); - } else { - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - singlehold: true, - }, - }); - this.touchpad_holding = true; - } - } - - _onTouchpadLongPressEnd(gesture) { - if (this.touchpad_holding) { - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - singlerelease: true, - }, - }); - this.touchpad_holding = false; - } - } - - _onTouchpadMotionTimeout() { - const diff_x = this.touchpad_motion_x - this.touchpad_motion_prev_x; - const diff_y = this.touchpad_motion_y - this.touchpad_motion_prev_y; - - this.device.sendPacket({ - type: 'kdeconnect.mousepad.request', - body: { - dx: diff_x, - dy: diff_y, - }, - }); - - this.touchpad_motion_prev_x = this.touchpad_motion_x; - this.touchpad_motion_prev_y = this.touchpad_motion_y; - return true; - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/notification.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/notification.js deleted file mode 100755 index 654e4655..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/notification.js +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import * as URI from '../utils/uri.js'; -import '../utils/ui.js'; - - -/** - * A dialog for repliable notifications. - */ -const ReplyDialog = GObject.registerClass({ - GTypeName: 'GSConnectNotificationReplyDialog', - Properties: { - 'device': GObject.ParamSpec.object( - 'device', - 'Device', - 'The device associated with this window', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'plugin': GObject.ParamSpec.object( - 'plugin', - 'Plugin', - 'The plugin that owns this notification', - GObject.ParamFlags.READWRITE, - GObject.Object - ), - 'uuid': GObject.ParamSpec.string( - 'uuid', - 'UUID', - 'The notification reply UUID', - GObject.ParamFlags.READWRITE, - null - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/notification-reply-dialog.ui', - Children: ['infobar', 'notification-title', 'notification-body', 'entry'], -}, class ReplyDialog extends Gtk.Dialog { - - _init(params) { - super._init({ - application: Gio.Application.get_default(), - device: params.device, - plugin: params.plugin, - uuid: params.uuid, - use_header_bar: true, - }); - - this.set_response_sensitive(Gtk.ResponseType.OK, false); - - // Info bar - this.device.bind_property( - 'connected', - this.infobar, - 'reveal-child', - GObject.BindingFlags.INVERT_BOOLEAN - ); - - // Notification Data - const headerbar = this.get_titlebar(); - headerbar.title = params.notification.appName; - headerbar.subtitle = this.device.name; - - this.notification_title.label = params.notification.title; - this.notification_body.label = URI.linkify(params.notification.text); - - // Message Entry/Send Button - this.device.bind_property( - 'connected', - this.entry, - 'sensitive', - GObject.BindingFlags.DEFAULT - ); - - this._connectedId = this.device.connect( - 'notify::connected', - this._onStateChanged.bind(this) - ); - - this._entryChangedId = this.entry.buffer.connect( - 'changed', - this._onStateChanged.bind(this) - ); - - this.restoreGeometry('notification-reply-dialog'); - - this.connect('destroy', this._onDestroy); - } - - _onDestroy(dialog) { - dialog.entry.buffer.disconnect(dialog._entryChangedId); - dialog.device.disconnect(dialog._connectedId); - } - - vfunc_delete_event() { - this.saveGeometry(); - - return false; - } - - vfunc_response(response_id) { - if (response_id === Gtk.ResponseType.OK) { - // Refuse to send empty or whitespace only messages - if (!this.entry.buffer.text.trim()) - return; - - this.plugin.replyNotification( - this.uuid, - this.entry.buffer.text - ); - } - - this.destroy(); - } - - get device() { - if (this._device === undefined) - this._device = null; - - return this._device; - } - - set device(device) { - this._device = device; - } - - get plugin() { - if (this._plugin === undefined) - this._plugin = null; - - return this._plugin; - } - - set plugin(plugin) { - this._plugin = plugin; - } - - get uuid() { - if (this._uuid === undefined) - this._uuid = null; - - return this._uuid; - } - - set uuid(uuid) { - this._uuid = uuid; - - // We must have a UUID - if (!uuid) { - this.destroy(); - debug('no uuid for repliable notification'); - } - } - - _onActivateLink(label, uri) { - Gtk.show_uri_on_window( - this.get_toplevel(), - uri.includes('://') ? uri : `https://${uri}`, - Gtk.get_current_event_time() - ); - - return true; - } - - _onStateChanged() { - if (this.device.connected && this.entry.buffer.text.trim()) - this.set_response_sensitive(Gtk.ResponseType.OK, true); - else - this.set_response_sensitive(Gtk.ResponseType.OK, false); - } -}); - -export default ReplyDialog; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/service.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/service.js deleted file mode 100755 index b84bb3d2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/ui/service.js +++ /dev/null @@ -1,252 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import system from 'system'; - -import Config from '../../config.js'; - - -/* - * Issue Header - */ -const ISSUE_HEADER = ` -GSConnect: ${Config.PACKAGE_VERSION} (${Config.IS_USER ? 'user' : 'system'}) -GJS: ${system.version} -Session: ${GLib.getenv('XDG_SESSION_TYPE')} -OS: ${GLib.get_os_info('PRETTY_NAME')} -`; - - -/** - * A dialog for selecting a device - */ -export const DeviceChooser = GObject.registerClass({ - GTypeName: 'GSConnectServiceDeviceChooser', - Properties: { - 'action-name': GObject.ParamSpec.string( - 'action-name', - 'Action Name', - 'The name of the associated action, like "sendFile"', - GObject.ParamFlags.READWRITE, - null - ), - 'action-target': GObject.param_spec_variant( - 'action-target', - 'Action Target', - 'The parameter for action invocations', - new GLib.VariantType('*'), - null, - GObject.ParamFlags.READWRITE - ), - }, - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/service-device-chooser.ui', - Children: ['device-list', 'cancel-button', 'select-button'], -}, class DeviceChooser extends Gtk.Dialog { - - _init(params = {}) { - super._init({ - use_header_bar: true, - application: Gio.Application.get_default(), - }); - this.set_keep_above(true); - - // HeaderBar - this.get_header_bar().subtitle = params.title; - - // Dialog Action - this.action_name = params.action_name; - this.action_target = params.action_target; - - // Device List - this.device_list.set_sort_func(this._sortDevices); - - this._devicesChangedId = this.application.settings.connect( - 'changed::devices', - this._onDevicesChanged.bind(this) - ); - this._onDevicesChanged(); - } - - vfunc_response(response_id) { - if (response_id === Gtk.ResponseType.OK) { - try { - const device = this.device_list.get_selected_row().device; - device.activate_action(this.action_name, this.action_target); - } catch (e) { - logError(e); - } - } - - this.destroy(); - } - - get action_name() { - if (this._action_name === undefined) - this._action_name = null; - - return this._action_name; - } - - set action_name(name) { - this._action_name = name; - } - - get action_target() { - if (this._action_target === undefined) - this._action_target = null; - - return this._action_target; - } - - set action_target(variant) { - this._action_target = variant; - } - - _onDeviceActivated(box, row) { - this.response(Gtk.ResponseType.OK); - } - - _onDeviceSelected(box) { - this.set_response_sensitive( - Gtk.ResponseType.OK, - (box.get_selected_row()) - ); - } - - _onDevicesChanged() { - // Collect known devices - const devices = {}; - - for (const [id, device] of this.application.manager.devices.entries()) - devices[id] = device; - - // Prune device rows - this.device_list.foreach(row => { - if (!devices.hasOwnProperty(row.name)) - row.destroy(); - else - delete devices[row.name]; - }); - - // Add new devices - for (const device of Object.values(devices)) { - const action = device.lookup_action(this.action_name); - - if (action === null) - continue; - - const row = new Gtk.ListBoxRow({ - visible: action.enabled, - }); - row.set_name(device.id); - row.device = device; - - action.bind_property( - 'enabled', - row, - 'visible', - Gio.SettingsBindFlags.DEFAULT - ); - - const grid = new Gtk.Grid({ - column_spacing: 12, - margin: 6, - visible: true, - }); - row.add(grid); - - const icon = new Gtk.Image({ - icon_name: device.icon_name, - pixel_size: 32, - visible: true, - }); - grid.attach(icon, 0, 0, 1, 1); - - const name = new Gtk.Label({ - label: device.name, - halign: Gtk.Align.START, - hexpand: true, - visible: true, - }); - grid.attach(name, 1, 0, 1, 1); - - this.device_list.add(row); - } - - if (this.device_list.get_selected_row() === null) - this.device_list.select_row(this.device_list.get_row_at_index(0)); - } - - _sortDevices(row1, row2) { - return row1.device.name.localeCompare(row2.device.name); - } -}); - - -/** - * A dialog for reporting an error. - */ -export const ErrorDialog = GObject.registerClass({ - GTypeName: 'GSConnectServiceErrorDialog', - Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/service-error-dialog.ui', - Children: [ - 'error-stack', - 'expander-arrow', - 'gesture', - 'report-button', - 'revealer', - ], -}, class ErrorDialog extends Gtk.Window { - - _init(error) { - super._init({ - application: Gio.Application.get_default(), - title: `GSConnect: ${error.name}`, - }); - this.set_keep_above(true); - - this.error = error; - this.error_stack.buffer.text = `${error.message}\n\n${error.stack}`; - this.gesture.connect('released', this._onReleased.bind(this)); - } - - _onClicked(button) { - if (this.report_button === button) { - const uri = this._buildUri(this.error.message, this.error.stack); - Gio.AppInfo.launch_default_for_uri_async(uri, null, null, null); - } - - this.destroy(); - } - - _onReleased(gesture, n_press) { - if (n_press === 1) - this.revealer.reveal_child = !this.revealer.reveal_child; - } - - _onRevealChild(revealer, pspec) { - this.expander_arrow.icon_name = this.revealer.reveal_child - ? 'pan-down-symbolic' - : 'pan-end-symbolic'; - } - - _buildUri(message, stack) { - const body = `\`\`\`${ISSUE_HEADER}\n${stack}\n\`\`\``; - const titleQuery = encodeURIComponent(message).replace('%20', '+'); - const bodyQuery = encodeURIComponent(body).replace('%20', '+'); - const uri = `${Config.PACKAGE_BUGREPORT}?title=${titleQuery}&body=${bodyQuery}`; - - // Reasonable URI length limit - if (uri.length > 2000) - return uri.substr(0, 2000); - - return uri; - } -}); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/dbus.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/dbus.js deleted file mode 100755 index f4a9d676..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/dbus.js +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GjsPrivate from 'gi://GjsPrivate'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - - -/* - * Some utility methods - */ -function toDBusCase(string) { - return string.replace(/(?:^\w|[A-Z]|\b\w)/g, (ltr, offset) => { - return ltr.toUpperCase(); - }).replace(/[\s_-]+/g, ''); -} - -function toUnderscoreCase(string) { - return string.replace(/(?:^\w|[A-Z]|_|\b\w)/g, (ltr, offset) => { - if (ltr === '_') - return ''; - - return (offset > 0) ? `_${ltr.toLowerCase()}` : ltr.toLowerCase(); - }).replace(/[\s-]+/g, ''); -} - - -/** - * DBus.Interface represents a DBus interface bound to an object instance, meant - * to be exported over DBus. - */ -export const Interface = GObject.registerClass({ - GTypeName: 'GSConnectDBusInterface', - Implements: [Gio.DBusInterface], - Properties: { - 'g-instance': GObject.ParamSpec.object( - 'g-instance', - 'Instance', - 'The delegate GObject', - GObject.ParamFlags.READWRITE, - GObject.Object.$gtype - ), - }, -}, class Interface extends GjsPrivate.DBusImplementation { - - _init(params) { - super._init({ - g_instance: params.g_instance, - g_interface_info: params.g_interface_info, - }); - - // Cache member lookups - this._instanceHandlers = []; - this._instanceMethods = {}; - this._instanceProperties = {}; - - const info = this.get_info(); - this.connect('handle-method-call', this._call.bind(this._instance, info)); - this.connect('handle-property-get', this._get.bind(this._instance, info)); - this.connect('handle-property-set', this._set.bind(this._instance, info)); - - // Automatically forward known signals - const id = this._instance.connect('notify', this._notify.bind(this)); - this._instanceHandlers.push(id); - - for (const signal of info.signals) { - const type = `(${signal.args.map(arg => arg.signature).join('')})`; - const id = this._instance.connect( - signal.name, - this._emit.bind(this, signal.name, type) - ); - - this._instanceHandlers.push(id); - } - - // Export if connection and object path were given - if (params.g_connection && params.g_object_path) - this.export(params.g_connection, params.g_object_path); - } - - get g_instance() { - if (this._instance === undefined) - this._instance = null; - - return this._instance; - } - - set g_instance(instance) { - this._instance = instance; - } - - /** - * Invoke an instance's method for a DBus method call. - * - * @param {Gio.DBusInterfaceInfo} info - The DBus interface - * @param {DBus.Interface} iface - The DBus interface - * @param {string} name - The DBus method name - * @param {GLib.Variant} parameters - The method parameters - * @param {Gio.DBusMethodInvocation} invocation - The method invocation info - */ - async _call(info, iface, name, parameters, invocation) { - let retval; - - // Invoke the instance method - try { - const args = parameters.unpack().map(parameter => { - if (parameter.get_type_string() === 'h') { - const message = invocation.get_message(); - const fds = message.get_unix_fd_list(); - const idx = parameter.deepUnpack(); - return fds.get(idx); - } else { - return parameter.recursiveUnpack(); - } - }); - - retval = await this[name](...args); - } catch (e) { - if (e instanceof GLib.Error) { - invocation.return_gerror(e); - } else { - // likely to be a normal JS error - if (!e.name.includes('.')) - e.name = `org.gnome.gjs.JSError.${e.name}`; - - invocation.return_dbus_error(e.name, e.message); - } - - logError(e, `${this}: ${name}`); - return; - } - - // `undefined` is an empty tuple on DBus - if (retval === undefined) - retval = new GLib.Variant('()', []); - - // Return the instance result or error - try { - if (!(retval instanceof GLib.Variant)) { - const args = info.lookup_method(name).out_args; - retval = new GLib.Variant( - `(${args.map(arg => arg.signature).join('')})`, - (args.length === 1) ? [retval] : retval - ); - } - - invocation.return_value(retval); - } catch (e) { - invocation.return_dbus_error( - 'org.gnome.gjs.JSError.ValueError', - 'Service implementation returned an incorrect value type' - ); - - logError(e, `${this}: ${name}`); - } - } - - _nativeProp(obj, name) { - if (this._instanceProperties[name] === undefined) { - let propName = name; - - if (propName in obj) - this._instanceProperties[name] = propName; - - if (this._instanceProperties[name] === undefined) { - propName = toUnderscoreCase(name); - - if (propName in obj) - this._instanceProperties[name] = propName; - } - } - - return this._instanceProperties[name]; - } - - _emit(name, type, obj, ...args) { - this.emit_signal(name, new GLib.Variant(type, args)); - } - - _get(info, iface, name) { - const nativeValue = this[iface._nativeProp(this, name)]; - const propertyInfo = info.lookup_property(name); - - if (nativeValue === undefined || propertyInfo === null) - return null; - - return new GLib.Variant(propertyInfo.signature, nativeValue); - } - - _set(info, iface, name, value) { - const nativeValue = value.recursiveUnpack(); - - this[iface._nativeProp(this, name)] = nativeValue; - } - - _notify(obj, pspec) { - const name = toDBusCase(pspec.name); - const propertyInfo = this.get_info().lookup_property(name); - - if (propertyInfo === null) - return; - - this.emit_property_changed( - name, - new GLib.Variant( - propertyInfo.signature, - // Adjust for GJS's '-'/'_' conversion - this._instance[pspec.name.replace(/-/gi, '_')] - ) - ); - } - - destroy() { - try { - for (const id of this._instanceHandlers) - this._instance.disconnect(id); - this._instanceHandlers = []; - - this.flush(); - this.unexport(); - } catch (e) { - logError(e); - } - } -}); - -/** - * Get a new, dedicated DBus connection on @busType - * - * @param {Gio.BusType} [busType] - a Gio.BusType constant - * @param {Gio.Cancellable} [cancellable] - an optional Gio.Cancellable - * @return {Promise<Gio.DBusConnection>} A new DBus connection - */ -export function newConnection(busType = Gio.BusType.SESSION, cancellable = null) { - return new Promise((resolve, reject) => { - Gio.DBusConnection.new_for_address( - Gio.dbus_address_get_for_bus_sync(busType, cancellable), - Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT | - Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION, - null, - cancellable, - (connection, res) => { - try { - resolve(Gio.DBusConnection.new_for_address_finish(res)); - } catch (e) { - reject(e); - } - } - ); - - }); -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/ui.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/ui.js deleted file mode 100755 index d0f31aa9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/ui.js +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Gtk from 'gi://Gtk'; - -import Config from '../../config.js'; - - -/* - * Window State - */ -Gtk.Window.prototype.restoreGeometry = function (context = 'default') { - this._windowState = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect.WindowState', - true - ), - path: `/org/gnome/shell/extensions/gsconnect/${context}/`, - }); - - // Size - const [width, height] = this._windowState.get_value('window-size').deepUnpack(); - - if (width && height) - this.set_default_size(width, height); - - // Maximized State - if (this._windowState.get_boolean('window-maximized')) - this.maximize(); -}; - -Gtk.Window.prototype.saveGeometry = function () { - const state = this.get_window().get_state(); - - // Maximized State - const maximized = (state & Gdk.WindowState.MAXIMIZED); - this._windowState.set_boolean('window-maximized', maximized); - - // Leave the size at the value before maximizing - if (maximized || (state & Gdk.WindowState.FULLSCREEN)) - return; - - // Size - const size = this.get_size(); - this._windowState.set_value('window-size', new GLib.Variant('(ii)', size)); -}; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/uri.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/uri.js deleted file mode 100755 index e7fca2c4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/service/utils/uri.js +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GLib from 'gi://GLib'; - - -/** - * The same regular expression used in GNOME Shell - * - * http://daringfireball.net/2010/07/improved_regex_for_matching_urls - */ -const _balancedParens = '\\((?:[^\\s()<>]+|(?:\\(?:[^\\s()<>]+\\)))*\\)'; -const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]'; -const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]'; - -const _urlRegexp = new RegExp( - '(^|' + _leadingJunk + ')' + - '(' + - '(?:' + - '(?:http|https)://' + // scheme:// - '|' + - 'www\\d{0,3}[.]' + // www. - '|' + - '[a-z0-9.\\-]+[.][a-z]{2,4}/' + // foo.xx/ - ')' + - '(?:' + // one or more: - '[^\\s()<>]+' + // run of non-space non-() - '|' + // or - _balancedParens + // balanced parens - ')+' + - '(?:' + // end with: - _balancedParens + // balanced parens - '|' + // or - _notTrailingJunk + // last non-junk char - ')' + - ')', 'gi'); - - -/** - * sms/tel URI RegExp (https://tools.ietf.org/html/rfc5724) - * - * A fairly lenient regexp for sms: URIs that allows tel: numbers with chars - * from global-number, local-number (without phone-context) and single spaces. - * This allows passing numbers directly from libfolks or GData without - * pre-processing. It also makes an allowance for URIs passed from Gio.File - * that always come in the form "sms:///". - */ -const _smsParam = "[\\w.!~*'()-]+=(?:[\\w.!~*'()-]|%[0-9A-F]{2})*"; -const _telParam = ";[a-zA-Z0-9-]+=(?:[\\w\\[\\]/:&+$.!~*'()-]|%[0-9A-F]{2})+"; -const _lenientDigits = '[+]?(?:[0-9A-F*#().-]| (?! )|%20(?!%20))+'; -const _lenientNumber = `${_lenientDigits}(?:${_telParam})*`; - -const _smsRegex = new RegExp( - '^' + - 'sms:' + // scheme - '(?:[/]{2,3})?' + // Gio.File returns ":///" - '(' + // one or more... - _lenientNumber + // phone numbers - '(?:,' + _lenientNumber + ')*' + // separated by commas - ')' + - '(?:\\?(' + // followed by optional... - _smsParam + // parameters... - '(?:&' + _smsParam + ')*' + // separated by "&" (unescaped) - '))?' + - '$', 'g'); // fragments (#foo) not allowed - - -const _numberRegex = new RegExp( - '^' + - '(' + _lenientDigits + ')' + // phone number digits - '((?:' + _telParam + ')*)' + // followed by optional parameters - '$', 'g'); - - -/** - * Searches @str for URLs and returns an array of objects with %url - * properties showing the matched URL string, and %pos properties indicating - * the position within @str where the URL was found. - * - * @param {string} str - the string to search - * @return {Object[]} the list of match objects, as described above - */ -export function findUrls(str) { - _urlRegexp.lastIndex = 0; - - const res = []; - let match; - - while ((match = _urlRegexp.exec(str))) { - const name = match[2]; - const url = GLib.uri_parse_scheme(name) ? name : `http://${name}`; - res.push({name, url, pos: match.index + match[1].length}); - } - - return res; -} - - -/** - * Return a string with URLs couched in <a> tags, parseable by Pango and - * using the same RegExp as GNOME Shell. - * - * @param {string} str - The string to be modified - * @param {string} [title] - An optional title (eg. alt text, tooltip) - * @return {string} the modified text - */ -export function linkify(str, title = null) { - const text = GLib.markup_escape_text(str, -1); - - _urlRegexp.lastIndex = 0; - - if (title) { - return text.replace( - _urlRegexp, - `$1<a href="$2" title="${title}">$2</a>` - ); - } else { - return text.replace(_urlRegexp, '$1<a href="$2">$2</a>'); - } -} - - -/** - * A simple parsing class for sms: URI's (https://tools.ietf.org/html/rfc5724) - */ -export default class URI { - constructor(uri) { - _smsRegex.lastIndex = 0; - const [, recipients, query] = _smsRegex.exec(uri); - - this.recipients = recipients.split(',').map(recipient => { - _numberRegex.lastIndex = 0; - const [, number, params] = _numberRegex.exec(recipient); - - if (params) { - for (const param of params.substr(1).split(';')) { - const [key, value] = param.split('='); - - // add phone-context to beginning of - if (key === 'phone-context' && value.startsWith('+')) - return value + unescape(number); - } - } - - return unescape(number); - }); - - if (query) { - for (const field of query.split('&')) { - const [key, value] = field.split('='); - - if (key === 'body') { - if (this.body) - throw URIError('duplicate "body" field'); - - this.body = value ? decodeURIComponent(value) : undefined; - } - } - } - } - - toString() { - const uri = `sms:${this.recipients.join(',')}`; - - return this.body ? `${uri}?body=${escape(this.body)}` : uri; - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/clipboard.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/clipboard.js deleted file mode 100755 index c9b61f35..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/clipboard.js +++ /dev/null @@ -1,380 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GjsPrivate from 'gi://GjsPrivate'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import Meta from 'gi://Meta'; - - -/* - * DBus Interface Info - */ -const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard'; -const DBUS_PATH = '/org/gnome/Shell/Extensions/GSConnect/Clipboard'; -const DBUS_NODE = Gio.DBusNodeInfo.new_for_xml(` -<node> - <interface name="org.gnome.Shell.Extensions.GSConnect.Clipboard"> - <!-- Methods --> - <method name="GetMimetypes"> - <arg direction="out" type="as" name="mimetypes"/> - </method> - <method name="GetText"> - <arg direction="out" type="s" name="text"/> - </method> - <method name="SetText"> - <arg direction="in" type="s" name="text"/> - </method> - <method name="GetValue"> - <arg direction="in" type="s" name="mimetype"/> - <arg direction="out" type="ay" name="value"/> - </method> - <method name="SetValue"> - <arg direction="in" type="ay" name="value"/> - <arg direction="in" type="s" name="mimetype"/> - </method> - - <!-- Signals --> - <signal name="OwnerChange"/> - </interface> -</node> -`); -const DBUS_INFO = DBUS_NODE.lookup_interface(DBUS_NAME); - - -/* - * Text Mimetypes - */ -const TEXT_MIMETYPES = [ - 'text/plain;charset=utf-8', - 'UTF8_STRING', - 'text/plain', - 'STRING', -]; - - -/* GSConnectClipboardPortal: - * - * A simple clipboard portal, especially useful on Wayland where GtkClipboard - * doesn't work in the background. - */ -export const Clipboard = GObject.registerClass({ - GTypeName: 'GSConnectShellClipboard', -}, class GSConnectShellClipboard extends GjsPrivate.DBusImplementation { - - _init(params = {}) { - super._init({ - g_interface_info: DBUS_INFO, - }); - - this._transferring = false; - - // Watch global selection - this._selection = global.display.get_selection(); - this._ownerChangedId = this._selection.connect( - 'owner-changed', - this._onOwnerChanged.bind(this) - ); - - // Prepare DBus interface - this._handleMethodCallId = this.connect( - 'handle-method-call', - this._onHandleMethodCall.bind(this) - ); - - this._nameId = Gio.DBus.own_name( - Gio.BusType.SESSION, - DBUS_NAME, - Gio.BusNameOwnerFlags.NONE, - this._onBusAcquired.bind(this), - null, - this._onNameLost.bind(this) - ); - } - - _onOwnerChanged(selection, type, source) { - /* We're only interested in the standard clipboard */ - if (type !== Meta.SelectionType.SELECTION_CLIPBOARD) - return; - - /* In Wayland an intermediate GMemoryOutputStream is used which triggers - * a second ::owner-changed emission, so we need to ensure we ignore - * that while the transfer is resolving. - */ - if (this._transferring) - return; - - this._transferring = true; - - /* We need to put our signal emission in an idle callback to ensure that - * Mutter's internal calls have finished resolving in the loop, or else - * we'll end up with the previous selection's content. - */ - GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - this.emit_signal('OwnerChange', null); - this._transferring = false; - - return GLib.SOURCE_REMOVE; - }); - } - - _onBusAcquired(connection, name) { - try { - this.export(connection, DBUS_PATH); - } catch (e) { - logError(e); - } - } - - _onNameLost(connection, name) { - try { - this.unexport(); - } catch (e) { - logError(e); - } - } - - async _onHandleMethodCall(iface, name, parameters, invocation) { - let retval; - - try { - const args = parameters.recursiveUnpack(); - - retval = await this[name](...args); - } catch (e) { - if (e instanceof GLib.Error) { - invocation.return_gerror(e); - } else { - if (!e.name.includes('.')) - e.name = `org.gnome.gjs.JSError.${e.name}`; - - invocation.return_dbus_error(e.name, e.message); - } - - return; - } - - if (retval === undefined) - retval = new GLib.Variant('()', []); - - try { - if (!(retval instanceof GLib.Variant)) { - const args = DBUS_INFO.lookup_method(name).out_args; - retval = new GLib.Variant( - `(${args.map(arg => arg.signature).join('')})`, - (args.length === 1) ? [retval] : retval - ); - } - - invocation.return_value(retval); - - // Without a response, the client will wait for timeout - } catch (e) { - invocation.return_dbus_error( - 'org.gnome.gjs.JSError.ValueError', - 'Service implementation returned an incorrect value type' - ); - } - } - - /** - * Get the available mimetypes of the current clipboard content - * - * @return {Promise<string[]>} A list of mime-types - */ - GetMimetypes() { - return new Promise((resolve, reject) => { - try { - const mimetypes = this._selection.get_mimetypes( - Meta.SelectionType.SELECTION_CLIPBOARD - ); - - resolve(mimetypes); - } catch (e) { - reject(e); - } - }); - } - - /** - * Get the text content of the clipboard - * - * @return {Promise<string>} Text content of the clipboard - */ - GetText() { - return new Promise((resolve, reject) => { - const mimetypes = this._selection.get_mimetypes( - Meta.SelectionType.SELECTION_CLIPBOARD); - - const mimetype = TEXT_MIMETYPES.find(type => mimetypes.includes(type)); - - if (mimetype !== undefined) { - const stream = Gio.MemoryOutputStream.new_resizable(); - - this._selection.transfer_async( - Meta.SelectionType.SELECTION_CLIPBOARD, - mimetype, -1, - stream, null, - (selection, res) => { - try { - selection.transfer_finish(res); - - const bytes = stream.steal_as_bytes(); - const bytearray = bytes.get_data(); - - resolve(new TextDecoder().decode(bytearray)); - } catch (e) { - reject(e); - } - } - ); - } else { - reject(new Error('text not available')); - } - }); - } - - /** - * Set the text content of the clipboard - * - * @param {string} text - text content to set - * @return {Promise} A promise for the operation - */ - SetText(text) { - return new Promise((resolve, reject) => { - try { - if (typeof text !== 'string') { - throw new Gio.DBusError({ - code: Gio.DBusError.INVALID_ARGS, - message: 'expected string', - }); - } - - const source = Meta.SelectionSourceMemory.new( - 'text/plain;charset=utf-8', GLib.Bytes.new(text)); - - this._selection.set_owner( - Meta.SelectionType.SELECTION_CLIPBOARD, source); - - resolve(); - } catch (e) { - reject(e); - } - }); - } - - /** - * Get the content of the clipboard with the type @mimetype. - * - * @param {string} mimetype - the mimetype to request - * @return {Promise<Uint8Array>} The content of the clipboard - */ - GetValue(mimetype) { - return new Promise((resolve, reject) => { - const stream = Gio.MemoryOutputStream.new_resizable(); - - this._selection.transfer_async( - Meta.SelectionType.SELECTION_CLIPBOARD, - mimetype, -1, - stream, null, - (selection, res) => { - try { - selection.transfer_finish(res); - - const bytes = stream.steal_as_bytes(); - - resolve(bytes.get_data()); - } catch (e) { - reject(e); - } - } - ); - }); - } - - /** - * Set the content of the clipboard to @value with the type @mimetype. - * - * @param {Uint8Array} value - the value to set - * @param {string} mimetype - the mimetype of the value - * @return {Promise} - A promise for the operation - */ - SetValue(value, mimetype) { - return new Promise((resolve, reject) => { - try { - const source = Meta.SelectionSourceMemory.new(mimetype, - GLib.Bytes.new(value)); - - this._selection.set_owner( - Meta.SelectionType.SELECTION_CLIPBOARD, source); - - resolve(); - } catch (e) { - reject(e); - } - }); - } - - destroy() { - if (this._selection && this._ownerChangedId > 0) { - this._selection.disconnect(this._ownerChangedId); - this._ownerChangedId = 0; - } - - if (this._nameId > 0) { - Gio.bus_unown_name(this._nameId); - this._nameId = 0; - } - - if (this._handleMethodCallId > 0) { - this.disconnect(this._handleMethodCallId); - this._handleMethodCallId = 0; - this.unexport(); - } - } -}); - - -let _portal = null; -let _portalId = 0; - -/** - * Watch for the service to start and export the clipboard portal when it does. - */ -export function watchService() { - if (GLib.getenv('XDG_SESSION_TYPE') !== 'wayland') - return; - - if (_portalId > 0) - return; - - _portalId = Gio.bus_watch_name( - Gio.BusType.SESSION, - 'org.gnome.Shell.Extensions.GSConnect', - Gio.BusNameWatcherFlags.NONE, - () => { - if (_portal === null) - _portal = new Clipboard(); - }, - () => { - if (_portal !== null) { - _portal.destroy(); - _portal = null; - } - } - ); -} - -/** - * Stop watching the service and export the portal if currently running. - */ -export function unwatchService() { - if (_portalId > 0) { - Gio.bus_unwatch_name(_portalId); - _portalId = 0; - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/device.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/device.js deleted file mode 100755 index 59e4d96e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/device.js +++ /dev/null @@ -1,380 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; - -import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -import {getIcon} from './utils.js'; - -import * as GMenu from './gmenu.js'; -import Tooltip from './tooltip.js'; - - -/** - * A battery widget with an icon, text percentage and time estimate tooltip - */ -export const Battery = GObject.registerClass({ - GTypeName: 'GSConnectShellDeviceBattery', -}, class Battery extends St.BoxLayout { - - _init(params) { - super._init({ - reactive: true, - style_class: 'gsconnect-device-battery', - track_hover: true, - }); - Object.assign(this, params); - - // Percent Label - this.label = new St.Label({ - y_align: Clutter.ActorAlign.CENTER, - }); - this.label.clutter_text.ellipsize = 0; - this.add_child(this.label); - - // Battery Icon - this.icon = new St.Icon({ - fallback_icon_name: 'battery-missing-symbolic', - icon_size: 16, - }); - this.add_child(this.icon); - - // Battery Estimate - this.tooltip = new Tooltip({ - parent: this, - text: null, - }); - - // Battery GAction - this._actionAddedId = this.device.action_group.connect( - 'action-added', - this._onActionChanged.bind(this) - ); - this._actionRemovedId = this.device.action_group.connect( - 'action-removed', - this._onActionChanged.bind(this) - ); - this._actionStateChangedId = this.device.action_group.connect( - 'action-state-changed', - this._onStateChanged.bind(this) - ); - - this._onActionChanged(this.device.action_group, 'battery'); - - // Cleanup on destroy - this.connect('destroy', this._onDestroy); - } - - _onActionChanged(action_group, action_name) { - if (action_name !== 'battery') - return; - - if (action_group.has_action('battery')) { - const value = action_group.get_action_state('battery'); - const [charging, icon_name, level, time] = value.deepUnpack(); - - this._state = { - charging: charging, - icon_name: icon_name, - level: level, - time: time, - }; - } else { - this._state = null; - } - - this._sync(); - } - - _onStateChanged(action_group, action_name, value) { - if (action_name !== 'battery') - return; - - const [charging, icon_name, level, time] = value.deepUnpack(); - - this._state = { - charging: charging, - icon_name: icon_name, - level: level, - time: time, - }; - - this._sync(); - } - - _getBatteryLabel() { - if (!this._state) - return null; - - const {charging, level, time} = this._state; - - if (level === 100) - // TRANSLATORS: When the battery level is 100% - return _('Fully Charged'); - - if (time === 0) - // TRANSLATORS: When no time estimate for the battery is available - // EXAMPLE: 42% (Estimating…) - return _('%d%% (Estimating…)').format(level); - - const total = time / 60; - const minutes = Math.floor(total % 60); - const hours = Math.floor(total / 60); - - if (charging) { - // TRANSLATORS: Estimated time until battery is charged - // EXAMPLE: 42% (1:15 Until Full) - return _('%d%% (%d\u2236%02d Until Full)').format( - level, - hours, - minutes - ); - } else { - // TRANSLATORS: Estimated time until battery is empty - // EXAMPLE: 42% (12:15 Remaining) - return _('%d%% (%d\u2236%02d Remaining)').format( - level, - hours, - minutes - ); - } - } - - _onDestroy(actor) { - actor.device.action_group.disconnect(actor._actionAddedId); - actor.device.action_group.disconnect(actor._actionRemovedId); - actor.device.action_group.disconnect(actor._actionStateChangedId); - } - - _sync() { - this.visible = !!this._state; - - if (!this.visible) - return; - - this.icon.icon_name = this._state.icon_name; - this.label.text = (this._state.level > -1) ? `${this._state.level}%` : ''; - this.tooltip.text = this._getBatteryLabel(); - } -}); - - -/** - * A cell signal strength widget with two icons - */ -export const SignalStrength = GObject.registerClass({ - GTypeName: 'GSConnectShellDeviceSignalStrength', -}, class SignalStrength extends St.BoxLayout { - - _init(params) { - super._init({ - reactive: true, - style_class: 'gsconnect-device-signal-strength', - track_hover: true, - }); - Object.assign(this, params); - - // Network Type Icon - this.networkTypeIcon = new St.Icon({ - fallback_icon_name: 'network-cellular-symbolic', - icon_size: 16, - }); - this.add_child(this.networkTypeIcon); - - // Signal Strength Icon - this.signalStrengthIcon = new St.Icon({ - fallback_icon_name: 'network-cellular-offline-symbolic', - icon_size: 16, - }); - this.add_child(this.signalStrengthIcon); - - // Network Type Text - this.tooltip = new Tooltip({ - parent: this, - text: null, - }); - - // ConnectivityReport GAction - this._actionAddedId = this.device.action_group.connect( - 'action-added', - this._onActionChanged.bind(this) - ); - this._actionRemovedId = this.device.action_group.connect( - 'action-removed', - this._onActionChanged.bind(this) - ); - this._actionStateChangedId = this.device.action_group.connect( - 'action-state-changed', - this._onStateChanged.bind(this) - ); - - this._onActionChanged(this.device.action_group, 'connectivityReport'); - - // Cleanup on destroy - this.connect('destroy', this._onDestroy); - } - - _onActionChanged(action_group, action_name) { - if (action_name !== 'connectivityReport') - return; - - if (action_group.has_action('connectivityReport')) { - const value = action_group.get_action_state('connectivityReport'); - const [ - cellular_network_type, - cellular_network_type_icon, - cellular_network_strength, - cellular_network_strength_icon, - hotspot_name, - hotspot_bssid, - ] = value.deepUnpack(); - - this._state = { - cellular_network_type: cellular_network_type, - cellular_network_type_icon: cellular_network_type_icon, - cellular_network_strength: cellular_network_strength, - cellular_network_strength_icon: cellular_network_strength_icon, - hotspot_name: hotspot_name, - hotspot_bssid: hotspot_bssid, - }; - } else { - this._state = null; - } - - this._sync(); - } - - _onStateChanged(action_group, action_name, value) { - if (action_name !== 'connectivityReport') - return; - - const [ - cellular_network_type, - cellular_network_type_icon, - cellular_network_strength, - cellular_network_strength_icon, - hotspot_name, - hotspot_bssid, - ] = value.deepUnpack(); - - this._state = { - cellular_network_type: cellular_network_type, - cellular_network_type_icon: cellular_network_type_icon, - cellular_network_strength: cellular_network_strength, - cellular_network_strength_icon: cellular_network_strength_icon, - hotspot_name: hotspot_name, - hotspot_bssid: hotspot_bssid, - }; - - this._sync(); - } - - _onDestroy(actor) { - actor.device.action_group.disconnect(actor._actionAddedId); - actor.device.action_group.disconnect(actor._actionRemovedId); - actor.device.action_group.disconnect(actor._actionStateChangedId); - } - - _sync() { - this.visible = !!this._state; - - if (!this.visible) - return; - - this.networkTypeIcon.icon_name = this._state.cellular_network_type_icon; - this.signalStrengthIcon.icon_name = this._state.cellular_network_strength_icon; - this.tooltip.text = this._state.cellular_network_type; - } -}); - - -/** - * A PopupMenu used as an information and control center for a device - */ -export class Menu extends PopupMenu.PopupMenuSection { - - constructor(params) { - super(); - Object.assign(this, params); - - this.actor.add_style_class_name('gsconnect-device-menu'); - - // Title - this._title = new PopupMenu.PopupSeparatorMenuItem(this.device.name); - this.addMenuItem(this._title); - - // Title -> Name - this._title.label.style_class = 'gsconnect-device-name'; - this._title.label.clutter_text.ellipsize = 0; - this.device.bind_property( - 'name', - this._title.label, - 'text', - GObject.BindingFlags.SYNC_CREATE - ); - - // Title -> Cellular Signal Strength - this._signalStrength = new SignalStrength({device: this.device}); - this._title.actor.add_child(this._signalStrength); - - // Title -> Battery - this._battery = new Battery({device: this.device}); - this._title.actor.add_child(this._battery); - - // Actions - let actions; - - if (this.menu_type === 'icon') { - actions = new GMenu.IconBox({ - action_group: this.device.action_group, - model: this.device.menu, - }); - } else if (this.menu_type === 'list') { - actions = new GMenu.ListBox({ - action_group: this.device.action_group, - model: this.device.menu, - }); - } - - this.addMenuItem(actions); - } - - isEmpty() { - return false; - } -} - - -/** - * An indicator representing a Device in the Status Area - */ -export const Indicator = GObject.registerClass({ - GTypeName: 'GSConnectDeviceIndicator', -}, class Indicator extends PanelMenu.Button { - - _init(params) { - super._init(0.0, `${params.device.name} Indicator`, false); - Object.assign(this, params); - - // Device Icon - this._icon = new St.Icon({ - gicon: getIcon(this.device.icon_name), - style_class: 'system-status-icon gsconnect-device-indicator', - }); - this.add_child(this._icon); - - // Menu - const menu = new Menu({ - device: this.device, - menu_type: 'icon', - }); - this.menu.addMenuItem(menu); - } -}); - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/gmenu.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/gmenu.js deleted file mode 100755 index 62ae0f1a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/gmenu.js +++ /dev/null @@ -1,647 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Atk from 'gi://Atk'; -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; - -import {getIcon} from './utils.js'; - -import Tooltip from './tooltip.js'; - - -/** - * Get a dictionary of a GMenuItem's attributes - * - * @param {Gio.MenuModel} model - The menu model containing the item - * @param {number} index - The index of the item in @model - * @return {Object} A dictionary of the item's attributes - */ -function getItemInfo(model, index) { - const info = { - target: null, - links: [], - }; - - // - let iter = model.iterate_item_attributes(index); - - while (iter.next()) { - const name = iter.get_name(); - let value = iter.get_value(); - - switch (name) { - case 'icon': - value = Gio.Icon.deserialize(value); - - if (value instanceof Gio.ThemedIcon) - value = getIcon(value.names[0]); - - info[name] = value; - break; - - case 'target': - info[name] = value; - break; - - default: - info[name] = value.unpack(); - } - } - - // Submenus & Sections - iter = model.iterate_item_links(index); - - while (iter.next()) { - info.links.push({ - name: iter.get_name(), - value: iter.get_value(), - }); - } - - return info; -} - - -/** - * - */ -export class ListBox extends PopupMenu.PopupMenuSection { - - constructor(params) { - super(); - Object.assign(this, params); - - // Main Actor - this.actor = new St.BoxLayout({ - x_expand: true, - clip_to_allocation: true, - }); - this.actor._delegate = this; - - // Item Box - this.box.clip_to_allocation = true; - this.box.x_expand = true; - this.box.add_style_class_name('gsconnect-list-box'); - this.box.set_pivot_point(1, 1); - this.actor.add_child(this.box); - - // Submenu Container - this.sub = new St.BoxLayout({ - clip_to_allocation: true, - vertical: false, - visible: false, - x_expand: true, - }); - this.sub.set_pivot_point(1, 1); - this.sub._delegate = this; - this.actor.add_child(this.sub); - - // Handle transitions - this._boxTransitionsCompletedId = this.box.connect( - 'transitions-completed', - this._onTransitionsCompleted.bind(this) - ); - - this._subTransitionsCompletedId = this.sub.connect( - 'transitions-completed', - this._onTransitionsCompleted.bind(this) - ); - - // Handle keyboard navigation - this._submenuCloseKeyId = this.sub.connect( - 'key-press-event', - this._onSubmenuCloseKey.bind(this) - ); - - // Refresh the menu when mapped - this._mappedId = this.actor.connect( - 'notify::mapped', - this._onMapped.bind(this) - ); - - // Watch the model for changes - this._itemsChangedId = this.model.connect( - 'items-changed', - this._onItemsChanged.bind(this) - ); - this._onItemsChanged(); - } - - _onMapped(actor) { - if (actor.mapped) { - this._onItemsChanged(); - - // We use this instead of close() to avoid touching finalized objects - } else { - this.box.set_opacity(255); - this.box.set_width(-1); - this.box.set_height(-1); - this.box.visible = true; - - this._submenu = null; - this.sub.set_opacity(0); - this.sub.set_width(0); - this.sub.set_height(0); - this.sub.visible = false; - this.sub.get_children().map(menu => menu.hide()); - } - } - - _onSubmenuCloseKey(actor, event) { - if (this.submenu && event.get_key_symbol() === Clutter.KEY_Left) { - this.submenu.submenu_for.setActive(true); - this.submenu = null; - return Clutter.EVENT_STOP; - } - - return Clutter.EVENT_PROPAGATE; - } - - _onSubmenuOpenKey(actor, event) { - const item = actor._delegate; - - if (item.submenu && event.get_key_symbol() === Clutter.KEY_Right) { - this.submenu = item.submenu; - item.submenu.firstMenuItem.setActive(true); - } - - return Clutter.EVENT_PROPAGATE; - } - - _onGMenuItemActivate(item, event) { - this.emit('activate', item); - - if (item.submenu) { - this.submenu = item.submenu; - } else if (item.action_name) { - this.action_group.activate_action( - item.action_name, - item.action_target - ); - this.itemActivated(); - } - } - - _addGMenuItem(info) { - const item = new PopupMenu.PopupMenuItem(info.label); - this.addMenuItem(item); - - if (info.action !== undefined) { - item.action_name = info.action.split('.')[1]; - item.action_target = info.target; - - item.actor.visible = this.action_group.get_action_enabled( - item.action_name - ); - } - - item.connectObject( - 'activate', - this._onGMenuItemActivate.bind(this), - this - ); - - return item; - } - - _addGMenuSection(model) { - const section = new ListBox({ - model: model, - action_group: this.action_group, - }); - this.addMenuItem(section); - } - - _addGMenuSubmenu(model, item) { - // Add an expander arrow to the item - const arrow = PopupMenu.arrowIcon(St.Side.RIGHT); - arrow.x_align = Clutter.ActorAlign.END; - arrow.x_expand = true; - item.actor.add_child(arrow); - - // Mark it as an expandable and open on right-arrow - item.actor.add_accessible_state(Atk.StateType.EXPANDABLE); - - item.actor.connect( - 'key-press-event', - this._onSubmenuOpenKey.bind(this) - ); - - // Create the submenu - item.submenu = new ListBox({ - model: model, - action_group: this.action_group, - submenu_for: item, - _parent: this, - }); - item.submenu.actor.hide(); - - // Add to the submenu container - this.sub.add_child(item.submenu.actor); - } - - _onItemsChanged(model, position, removed, added) { - // Clear the menu - this.removeAll(); - this.sub.get_children().map(child => child.destroy()); - - for (let i = 0, len = this.model.get_n_items(); i < len; i++) { - const info = getItemInfo(this.model, i); - let item; - - // A regular item - if (info.hasOwnProperty('label')) - item = this._addGMenuItem(info); - - for (const link of info.links) { - // Submenu - if (link.name === 'submenu') { - this._addGMenuSubmenu(link.value, item); - - // Section - } else if (link.name === 'section') { - this._addGMenuSection(link.value); - - // len is length starting at 1 - if (i + 1 < len) - this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - } - } - } - - // If this is a submenu of another item... - if (this.submenu_for) { - // Prepend an "<= Go Back" item, bold with a unicode arrow - const prev = new PopupMenu.PopupMenuItem(this.submenu_for.label.text); - prev.label.style = 'font-weight: bold;'; - const prevArrow = PopupMenu.arrowIcon(St.Side.LEFT); - prev.replace_child(prev._ornamentIcon, prevArrow); - this.addMenuItem(prev, 0); - - prev.connectObject('activate', (item, event) => { - this.emit('activate', item); - this._parent.submenu = null; - }, this); - } - } - - _onTransitionsCompleted(actor) { - if (this.submenu) { - this.box.visible = false; - } else { - this.sub.visible = false; - this.sub.get_children().map(menu => menu.hide()); - } - } - - get submenu() { - return this._submenu || null; - } - - set submenu(submenu) { - // Get the current allocation to hold the menu width - const allocation = this.actor.allocation; - const width = Math.max(0, allocation.x2 - allocation.x1); - - // Prepare the appropriate child for tweening - if (submenu) { - this.sub.set_opacity(0); - this.sub.set_width(0); - this.sub.set_height(0); - this.sub.visible = true; - } else { - this.box.set_opacity(0); - this.box.set_width(0); - this.sub.set_height(0); - this.box.visible = true; - } - - // Setup the animation - this.box.save_easing_state(); - this.box.set_easing_mode(Clutter.AnimationMode.EASE_IN_OUT_CUBIC); - this.box.set_easing_duration(250); - - this.sub.save_easing_state(); - this.sub.set_easing_mode(Clutter.AnimationMode.EASE_IN_OUT_CUBIC); - this.sub.set_easing_duration(250); - - if (submenu) { - submenu.actor.show(); - - this.sub.set_opacity(255); - this.sub.set_width(width); - this.sub.set_height(-1); - - this.box.set_opacity(0); - this.box.set_width(0); - this.box.set_height(0); - } else { - this.box.set_opacity(255); - this.box.set_width(width); - this.box.set_height(-1); - - this.sub.set_opacity(0); - this.sub.set_width(0); - this.sub.set_height(0); - } - - // Reset the animation - this.box.restore_easing_state(); - this.sub.restore_easing_state(); - - // - this._submenu = submenu; - } - - destroy() { - this.actor.disconnect(this._mappedId); - this.box.disconnect(this._boxTransitionsCompletedId); - this.sub.disconnect(this._subTransitionsCompletedId); - this.sub.disconnect(this._submenuCloseKeyId); - this.model.disconnect(this._itemsChangedId); - - super.destroy(); - } -} - - -/** - * A St.Button subclass for iconic GMenu items - */ -export const IconButton = GObject.registerClass({ - GTypeName: 'GSConnectShellIconButton', -}, class Button extends St.Button { - - _init(params) { - super._init({ - style_class: 'gsconnect-icon-button', - can_focus: true, - }); - Object.assign(this, params); - - // Item attributes - if (params.info.hasOwnProperty('action')) - this.action_name = params.info.action.split('.')[1]; - - if (params.info.hasOwnProperty('target')) - this.action_target = params.info.target; - - if (params.info.hasOwnProperty('label')) { - this.tooltip = new Tooltip({ - parent: this, - markup: params.info.label, - }); - - this.accessible_name = params.info.label; - } - - if (params.info.hasOwnProperty('icon')) - this.child = new St.Icon({gicon: params.info.icon}); - - // Submenu - for (const link of params.info.links) { - if (link.name === 'submenu') { - this.add_accessible_state(Atk.StateType.EXPANDABLE); - this.toggle_mode = true; - this.connect('notify::checked', this._onChecked); - - this.submenu = new ListBox({ - model: link.value, - action_group: this.action_group, - _parent: this._parent, - }); - - this.submenu.actor.style_class = 'popup-sub-menu'; - this.submenu.actor.visible = false; - } - } - } - - // This is (reliably?) emitted before ::clicked - _onChecked(button) { - if (button.checked) { - button.add_accessible_state(Atk.StateType.EXPANDED); - button.add_style_pseudo_class('active'); - } else { - button.remove_accessible_state(Atk.StateType.EXPANDED); - button.remove_style_pseudo_class('active'); - } - } - - // This is (reliably?) emitted after notify::checked - vfunc_clicked(clicked_button) { - // Unless this has a submenu, activate the action and close the menu - if (!this.toggle_mode) { - this._parent._getTopMenu().close(); - - this.action_group.activate_action( - this.action_name, - this.action_target - ); - - // StButton.checked has already been toggled so we're opening - } else if (this.checked) { - this._parent.submenu = this.submenu; - - // If this is the active submenu being closed, animate-close it - } else if (this._parent.submenu === this.submenu) { - this._parent.submenu = null; - } - } -}); - - -export class IconBox extends PopupMenu.PopupMenuSection { - - constructor(params) { - super(); - Object.assign(this, params); - - // Main Actor - this.actor = new St.BoxLayout({ - vertical: true, - x_expand: true, - }); - this.actor._delegate = this; - - // Button Box - this.box._delegate = this; - this.box.style_class = 'gsconnect-icon-box'; - this.box.vertical = false; - this.actor.add_child(this.box); - - // Submenu Container - this.sub = new St.BoxLayout({ - clip_to_allocation: true, - vertical: true, - x_expand: true, - }); - this.sub.connect('transitions-completed', this._onTransitionsCompleted); - this.sub._delegate = this; - this.actor.add_child(this.sub); - - // Track menu items so we can use ::items-changed - this._menu_items = new Map(); - - // PopupMenu - this._mappedId = this.actor.connect( - 'notify::mapped', - this._onMapped.bind(this) - ); - - // GMenu - this._itemsChangedId = this.model.connect( - 'items-changed', - this._onItemsChanged.bind(this) - ); - - // GActions - this._actionAddedId = this.action_group.connect( - 'action-added', - this._onActionChanged.bind(this) - ); - this._actionEnabledChangedId = this.action_group.connect( - 'action-enabled-changed', - this._onActionChanged.bind(this) - ); - this._actionRemovedId = this.action_group.connect( - 'action-removed', - this._onActionChanged.bind(this) - ); - } - - destroy() { - this.actor.disconnect(this._mappedId); - this.model.disconnect(this._itemsChangedId); - this.action_group.disconnect(this._actionAddedId); - this.action_group.disconnect(this._actionEnabledChangedId); - this.action_group.disconnect(this._actionRemovedId); - - super.destroy(); - } - - get submenu() { - return this._submenu || null; - } - - set submenu(submenu) { - if (submenu) { - for (const button of this.box.get_children()) { - if (button.submenu && this._submenu && button.submenu !== submenu) { - button.checked = false; - button.submenu.actor.hide(); - } - } - - this.sub.set_height(0); - submenu.actor.show(); - } - - this.sub.save_easing_state(); - this.sub.set_easing_duration(250); - this.sub.set_easing_mode(Clutter.AnimationMode.EASE_IN_OUT_CUBIC); - - this.sub.set_height(submenu ? submenu.actor.get_preferred_size()[1] : 0); - this.sub.restore_easing_state(); - - this._submenu = submenu; - } - - _onMapped(actor) { - if (!actor.mapped) { - this._submenu = null; - - for (const button of this.box.get_children()) - button.checked = false; - - for (const submenu of this.sub.get_children()) - submenu.hide(); - } - } - - _onActionChanged(group, name, enabled) { - const menuItem = this._menu_items.get(name); - - if (menuItem !== undefined) - menuItem.visible = group.get_action_enabled(name); - } - - _onItemsChanged(model, position, removed, added) { - // Remove items - while (removed > 0) { - const button = this.box.get_child_at_index(position); - const action_name = button.action_name; - - if (button.submenu) - button.submenu.destroy(); - - button.destroy(); - - this._menu_items.delete(action_name); - removed--; - } - - // Add items - for (let i = 0; i < added; i++) { - const index = position + i; - - // Create an iconic button - const button = new IconButton({ - action_group: this.action_group, - info: getItemInfo(model, index), - // NOTE: Because this doesn't derive from a PopupMenu class - // it lacks some things its parent will expect from it - _parent: this, - _delegate: null, - }); - - // Set the visibility based on the enabled state - if (button.action_name !== undefined) { - button.visible = this.action_group.get_action_enabled( - button.action_name - ); - } - - // If it has a submenu, add it as a sibling - if (button.submenu) - this.sub.add_child(button.submenu.actor); - - // Track the item if it has an action - if (button.action_name !== undefined) - this._menu_items.set(button.action_name, button); - - // Insert it in the box at the defined position - this.box.insert_child_at_index(button, index); - } - } - - _onTransitionsCompleted(actor) { - const menu = actor._delegate; - - for (const button of menu.box.get_children()) { - if (button.submenu && button.submenu !== menu.submenu) { - button.checked = false; - button.submenu.actor.hide(); - } - } - - menu.sub.set_height(-1); - } - - // PopupMenu.PopupMenuBase overrides - isEmpty() { - return (this.box.get_children().length === 0); - } - - _setParent(parent) { - super._setParent(parent); - this._onItemsChanged(this.model, 0, 0, this.model.get_n_items()); - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/input.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/input.js deleted file mode 100755 index b2ef07e2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/input.js +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; - -import Config from '../config.js'; - -export class LockscreenRemoteAccess { - - constructor() { - this._inhibitor = null; - this._settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect', - null - ), - path: '/org/gnome/shell/extensions/gsconnect/', - }); - } - - patchInhibitor() { - if (this._inhibitor) - return; - - if (this._settings.get_boolean('keep-alive-when-locked')) { - this._inhibitor = global.backend.get_remote_access_controller().inhibit_remote_access; - global.backend.get_remote_access_controller().inhibit_remote_access = () => {}; - } - } - - unpatchInhibitor() { - if (!this._inhibitor) - return; - global.backend.get_remote_access_controller().inhibit_remote_access = this._inhibitor; - this._inhibitor = null; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/keybindings.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/keybindings.js deleted file mode 100755 index 442fa0df..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/keybindings.js +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; - - -/** - * Keybindings.Manager is a simple convenience class for managing keyboard - * shortcuts in GNOME Shell. You bind a shortcut using add(), which on success - * will return a non-zero action id that can later be used with remove() to - * unbind the shortcut. - * - * Accelerators are accepted in the form returned by Gtk.accelerator_name() and - * callbacks are invoked directly, so should be complete closures. - * - * References: - * https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html - * https://developer.gnome.org/meta/stable/MetaDisplay.html - * https://developer.gnome.org/meta/stable/meta-MetaKeybinding.html - * https://gitlab.gnome.org/GNOME/gnome-shell/blob/master/js/ui/windowManager.js#L1093-1112 - */ -export class Manager { - - constructor() { - this._keybindings = new Map(); - - this._acceleratorActivatedId = global.display.connect( - 'accelerator-activated', - this._onAcceleratorActivated.bind(this) - ); - } - - _onAcceleratorActivated(display, action, inputDevice, timestamp) { - try { - const binding = this._keybindings.get(action); - - if (binding !== undefined) - binding.callback(); - } catch (e) { - logError(e); - } - } - - /** - * Add a keybinding with callback - * - * @param {string} accelerator - An accelerator in the form '<Control>q' - * @param {Function} callback - A callback for the accelerator - * @return {number} A non-zero action id on success, or 0 on failure - */ - add(accelerator, callback) { - try { - const action = global.display.grab_accelerator(accelerator, 0); - - if (action === Meta.KeyBindingAction.NONE) - throw new Error(`Failed to add keybinding: '${accelerator}'`); - - const name = Meta.external_binding_name_for_action(action); - Main.wm.allowKeybinding(name, Shell.ActionMode.ALL); - this._keybindings.set(action, {name: name, callback: callback}); - - return action; - } catch (e) { - logError(e); - } - } - - /** - * Remove a keybinding - * - * @param {number} action - A non-zero action id returned by add() - */ - remove(action) { - try { - const binding = this._keybindings.get(action); - global.display.ungrab_accelerator(action); - Main.wm.allowKeybinding(binding.name, Shell.ActionMode.NONE); - this._keybindings.delete(action); - } catch (e) { - logError(new Error(`Failed to remove keybinding: ${e.message}`)); - } - } - - /** - * Remove all keybindings - */ - removeAll() { - for (const action of this._keybindings.keys()) - this.remove(action); - } - - /** - * Destroy the keybinding manager and remove all keybindings - */ - destroy() { - global.display.disconnect(this._acceleratorActivatedId); - this.removeAll(); - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/notification.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/notification.js deleted file mode 100755 index 78b7f54b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/notification.js +++ /dev/null @@ -1,453 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; -import * as Calendar from 'resource:///org/gnome/shell/ui/calendar.js'; -import * as NotificationDaemon from 'resource:///org/gnome/shell/ui/notificationDaemon.js'; - -import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; -import {getIcon} from './utils.js'; - -const APP_ID = 'org.gnome.Shell.Extensions.GSConnect'; -const APP_PATH = '/org/gnome/Shell/Extensions/GSConnect'; - - -// deviceId Pattern (<device-id>|<remote-id>) -const DEVICE_REGEX = new RegExp(/^([^|]+)\|([\s\S]+)$/); - -// requestReplyId Pattern (<device-id>|<remote-id>)|<reply-id>) -const REPLY_REGEX = new RegExp(/^([^|]+)\|([\s\S]+)\|([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$/, 'i'); - - -/** - * Extracted from notificationDaemon.js, as it's no longer exported - * https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/notificationDaemon.js#L556 - * @returns {{ 'desktop-startup-id': string }} Object with ID containing current time - */ -function getPlatformData() { - const startupId = GLib.Variant.new('s', `_TIME${global.get_current_time()}`); - return {'desktop-startup-id': startupId}; -} - -// This is no longer directly exported, so we do this instead for now -const GtkNotificationDaemon = Main.notificationDaemon._gtkNotificationDaemon.constructor; - - -/** - * A slightly modified Notification Banner with an entry field - */ -const NotificationBanner = GObject.registerClass({ - GTypeName: 'GSConnectNotificationBanner', -}, class NotificationBanner extends Calendar.NotificationMessage { - - constructor(notification) { - super(notification); - if (notification.requestReplyId !== undefined) - this._addReplyAction(); - } - - _addReplyAction() { - if (!this._buttonBox) { - this._buttonBox = new St.BoxLayout({ - style_class: 'notification-buttons-bin', - x_expand: true, - }); - this.setActionArea(this._buttonBox); - global.focus_manager.add_group(this._buttonBox); - } - - // Reply Button - const button = new St.Button({ - style_class: 'notification-button', - label: _('Reply'), - x_expand: true, - can_focus: true, - }); - - button.connect( - 'clicked', - this._onEntryRequested.bind(this) - ); - - this._buttonBox.add_child(button); - - // Reply Entry - this._replyEntry = new St.Entry({ - can_focus: true, - hint_text: _('Type a message'), - style_class: 'chat-response', - x_expand: true, - visible: false, - }); - - this._buttonBox.add_child(this._replyEntry); - } - - _onEntryRequested(button) { - this.focused = true; - - for (const child of this._buttonBox.get_children()) - child.visible = (child === this._replyEntry); - - // Release the notification focus with the entry focus - this._replyEntry.connect( - 'key-focus-out', - this._onEntryDismissed.bind(this) - ); - - this._replyEntry.clutter_text.connect( - 'activate', - this._onEntryActivated.bind(this) - ); - - this._replyEntry.grab_key_focus(); - } - - _onEntryDismissed(entry) { - this.focused = false; - this.emit('unfocused'); - } - - _onEntryActivated(clutter_text) { - // Refuse to send empty replies - if (clutter_text.text === '') - return; - - // Copy the text, then clear the entry - const text = clutter_text.text; - clutter_text.text = ''; - - const {deviceId, requestReplyId} = this.notification; - - const target = new GLib.Variant('(ssbv)', [ - deviceId, - 'replyNotification', - true, - new GLib.Variant('(ssa{ss})', [requestReplyId, text, {}]), - ]); - const platformData = getPlatformData(); - - Gio.DBus.session.call( - APP_ID, - APP_PATH, - 'org.freedesktop.Application', - 'ActivateAction', - GLib.Variant.new('(sava{sv})', ['device', [target], platformData]), - null, - Gio.DBusCallFlags.NO_AUTO_START, - -1, - null, - (connection, res) => { - try { - connection.call_finish(res); - } catch (e) { - // Silence errors - } - } - ); - - this.close(); - } -}); - - -/** - * A custom notification source for spawning notifications and closing device - * notifications. This source isn't actually used, but it's methods are patched - * into existing sources. - */ -const Source = GObject.registerClass({ - GTypeName: 'GSConnectNotificationSource', -}, class Source extends NotificationDaemon.GtkNotificationDaemonAppSource { - - _closeGSConnectNotification(notification, reason) { - if (reason !== MessageTray.NotificationDestroyedReason.DISMISSED) - return; - - // Avoid sending the request multiple times - if (notification._remoteClosed || notification.remoteId === undefined) - return; - - notification._remoteClosed = true; - - const target = new GLib.Variant('(ssbv)', [ - notification.deviceId, - 'closeNotification', - true, - new GLib.Variant('s', notification.remoteId), - ]); - const platformData = getPlatformData(); - - Gio.DBus.session.call( - APP_ID, - APP_PATH, - 'org.freedesktop.Application', - 'ActivateAction', - GLib.Variant.new('(sava{sv})', ['device', [target], platformData]), - null, - Gio.DBusCallFlags.NO_AUTO_START, - -1, - null, - (connection, res) => { - try { - connection.call_finish(res); - } catch (e) { - // If we fail, reset in case we can try again - notification._remoteClosed = false; - } - } - ); - } - - /* - * Parse the id to determine if it's a repliable notification, device - * notification or a regular local notification - */ - _parseNotificationId(notificationId) { - let idMatch, deviceId, requestReplyId, remoteId, localId; - - if ((idMatch = REPLY_REGEX.exec(notificationId))) { - [, deviceId, remoteId, requestReplyId] = idMatch; - localId = `${deviceId}|${remoteId}`; - - } else if ((idMatch = DEVICE_REGEX.exec(notificationId))) { - [, deviceId, remoteId] = idMatch; - localId = `${deviceId}|${remoteId}`; - - } else { - localId = notificationId; - } - return [idMatch, deviceId, requestReplyId, remoteId, localId]; - } - - /* - * Add notification to source or update existing notification with extra - * GsConnect information - */ - _createNotification(notification) { - const [idMatch, deviceId, requestReplyId, remoteId, localId] = this._parseNotificationId(notification.id); - const cachedNotification = this._notifications[localId]; - - // Check if this is a repeat - if (cachedNotification) { - cachedNotification.requestReplyId = requestReplyId; - - // Bail early If @notificationParams represents an exact repeat - const title = notification.title; - const body = notification.body - ? notification.body - : null; - - if (cachedNotification.title === title && - cachedNotification.body === body) - return cachedNotification; - - cachedNotification.title = title; - cachedNotification.body = body; - - return cachedNotification; - } - - // Device Notification - if (idMatch) { - notification.deviceId = deviceId; - notification.remoteId = remoteId; - notification.requestReplyId = requestReplyId; - - notification.connect('destroy', (notification, reason) => { - this._closeGSConnectNotification(notification, reason); - delete this._notifications[localId]; - }); - - // Service Notification - } else { - notification.connect('destroy', (notification, reason) => { - delete this._notifications[localId]; - }); - } - - this._notifications[localId] = notification; - return notification; - } - - /* - * Override to control notification spawning - */ - addNotification(notification) { - this._notificationPending = true; - - // Fix themed icons - if (notification.icon) { - let gicon = notification.icon; - - if (gicon instanceof Gio.ThemedIcon) { - gicon = getIcon(gicon.names[0]); - notification.icon = gicon.serialize(); - } - } - - const createdNotification = this._createNotification(notification); - this._addNotificationToMessageTray(createdNotification); - - this._notificationPending = false; - } - - /* - * Reimplementation of MessageTray.addNotification to raise the usual - * notification limit (3) - */ - _addNotificationToMessageTray(notification) { - if (this.notifications.includes(notification)) { - notification.acknowledged = false; - return; - } - - while (this.notifications.length >= 10) { - const [oldest] = this.notifications; - oldest.destroy(MessageTray.NotificationDestroyedReason.EXPIRED); - } - - notification.connect('destroy', this._onNotificationDestroy.bind(this)); - notification.connect('notify::acknowledged', () => { - this.countUpdated(); - - // If acknowledged was set to false try to show the notification again - if (!notification.acknowledged) - this.emit('notification-request-banner', notification); - }); - this.notifications.push(notification); - - this.emit('notification-added', notification); - this.emit('notification-request-banner', notification); - } - - createBanner(notification) { - return new NotificationBanner(notification); - } -}); - - -/** - * If there is an active GtkNotificationDaemonAppSource for GSConnect when the - * extension is loaded, it has to be patched in place. - */ -export function patchGSConnectNotificationSource() { - const source = Main.notificationDaemon._gtkNotificationDaemon._sources[APP_ID]; - - if (source !== undefined) { - // Patch in the subclassed methods - source._closeGSConnectNotification = Source.prototype._closeGSConnectNotification; - source._parseNotificationId = Source.prototype._parseNotificationId; - source._createNotification = Source.prototype._createNotification; - source.addNotification = Source.prototype.addNotification; - source._addNotificationToMessageTray = Source.prototype._addNotificationToMessageTray; - source.createBanner = Source.prototype.createBanner; - - // Connect to existing notifications - for (const notification of Object.values(source._notifications)) { - - const _id = notification.connect('destroy', (notification, reason) => { - source._closeGSConnectNotification(notification, reason); - notification.disconnect(_id); - }); - } - } -} - - -/** - * Wrap GtkNotificationDaemon._ensureAppSource() to patch GSConnect's app source - * https://gitlab.gnome.org/GNOME/gnome-shell/blob/master/js/ui/notificationDaemon.js#L742-755 - */ -const __ensureAppSource = GtkNotificationDaemon.prototype._ensureAppSource; - -// eslint-disable-next-line func-style -const _ensureAppSource = function (appId) { - const source = __ensureAppSource.call(this, appId); - - if (source._appId === APP_ID) { - source._closeGSConnectNotification = Source.prototype._closeGSConnectNotification; - source._parseNotificationId = Source.prototype._parseNotificationId; - source._createNotification = Source.prototype._createNotification; - source.addNotification = Source.prototype.addNotification; - source._addNotificationToMessageTray = Source.prototype._addNotificationToMessageTray; - source.createBanner = Source.prototype.createBanner; - } - - return source; -}; - - -export function patchGtkNotificationDaemon() { - GtkNotificationDaemon.prototype._ensureAppSource = _ensureAppSource; -} - - -export function unpatchGtkNotificationDaemon() { - GtkNotificationDaemon.prototype._ensureAppSource = __ensureAppSource; -} - -/** - * We patch other Gtk notification sources so we can notify remote devices when - * notifications have been closed locally. - */ -const _addNotification = NotificationDaemon.GtkNotificationDaemonAppSource.prototype.addNotification; - -export function patchGtkNotificationSources() { - // eslint-disable-next-line func-style - const _withdrawGSConnectNotification = function (id, notification, reason) { - if (reason !== MessageTray.NotificationDestroyedReason.DISMISSED) - return; - - // Avoid sending the request multiple times - if (notification._remoteWithdrawn) - return; - - notification._remoteWithdrawn = true; - - // Recreate the notification id as it would've been sent - const target = new GLib.Variant('(ssbv)', [ - '*', - 'withdrawNotification', - true, - new GLib.Variant('s', `gtk|${this._appId}|${id}`), - ]); - const platformData = getPlatformData(); - - Gio.DBus.session.call( - APP_ID, - APP_PATH, - 'org.freedesktop.Application', - 'ActivateAction', - GLib.Variant.new('(sava{sv})', ['device', [target], platformData]), - null, - Gio.DBusCallFlags.NO_AUTO_START, - -1, - null, - (connection, res) => { - try { - connection.call_finish(res); - } catch (e) { - // If we fail, reset in case we can try again - notification._remoteWithdrawn = false; - } - } - ); - }; - - NotificationDaemon.GtkNotificationDaemonAppSource.prototype._withdrawGSConnectNotification = _withdrawGSConnectNotification; -} - - -export function unpatchGtkNotificationSources() { - NotificationDaemon.GtkNotificationDaemonAppSource.prototype.addNotification = _addNotification; - delete NotificationDaemon.GtkNotificationDaemonAppSource.prototype._withdrawGSConnectNotification; -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/tooltip.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/tooltip.js deleted file mode 100755 index 2996ce8e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/tooltip.js +++ /dev/null @@ -1,309 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Pango from 'gi://Pango'; -import St from 'gi://St'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - - -/** - * An StTooltip for ClutterActors - * - * Adapted from: https://github.com/RaphaelRochet/applications-overview-tooltip - * See also: https://github.com/GNOME/gtk/blob/master/gtk/gtktooltip.c - */ -export let TOOLTIP_BROWSE_ID = 0; -export let TOOLTIP_BROWSE_MODE = false; - -export default class Tooltip { - - constructor(params) { - Object.assign(this, params); - - this._bin = null; - this._hoverTimeoutId = 0; - this._showing = false; - - this._destroyId = this.parent.connect( - 'destroy', - this.destroy.bind(this) - ); - - this._hoverId = this.parent.connect( - 'notify::hover', - this._onHover.bind(this) - ); - - this._buttonPressEventId = this.parent.connect( - 'button-press-event', - this._hide.bind(this) - ); - } - - get custom() { - if (this._custom === undefined) - this._custom = null; - - return this._custom; - } - - set custom(actor) { - this._custom = actor; - this._markup = null; - this._text = null; - - if (this._showing) - this._show(); - } - - get gicon() { - if (this._gicon === undefined) - this._gicon = null; - - return this._gicon; - } - - set gicon(gicon) { - this._gicon = gicon; - - if (this._showing) - this._show(); - } - - get icon() { - return (this.gicon) ? this.gicon.name : null; - } - - set icon(icon_name) { - if (!icon_name) - this.gicon = null; - else - this.gicon = new Gio.ThemedIcon({name: icon_name}); - } - - get markup() { - if (this._markup === undefined) - this._markup = null; - - return this._markup; - } - - set markup(text) { - this._markup = text; - this._text = null; - - if (this._showing) - this._show(); - } - - get text() { - if (this._text === undefined) - this._text = null; - - return this._text; - } - - set text(text) { - this._markup = null; - this._text = text; - - if (this._showing) - this._show(); - } - - get x_offset() { - if (this._x_offset === undefined) - this._x_offset = 0; - - return this._x_offset; - } - - set x_offset(offset) { - this._x_offset = (Number.isInteger(offset)) ? offset : 0; - } - - get y_offset() { - if (this._y_offset === undefined) - this._y_offset = 0; - - return this._y_offset; - } - - set y_offset(offset) { - this._y_offset = (Number.isInteger(offset)) ? offset : 0; - } - - _show() { - if (this.text === null && this.markup === null) - return this._hide(); - - if (this._bin === null) { - this._bin = new St.Bin({ - style_class: 'osd-window gsconnect-tooltip', - opacity: 232, - }); - - if (this.custom) { - this._bin.child = this.custom; - } else { - this._bin.child = new St.BoxLayout({vertical: false}); - - if (this.gicon) { - this._bin.child.icon = new St.Icon({ - gicon: this.gicon, - y_align: St.Align.START, - }); - this._bin.child.icon.set_y_align(Clutter.ActorAlign.START); - this._bin.child.add_child(this._bin.child.icon); - } - - this.label = new St.Label({text: this.markup || this.text}); - this.label.clutter_text.line_wrap = true; - this.label.clutter_text.line_wrap_mode = Pango.WrapMode.WORD; - this.label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; - this.label.clutter_text.use_markup = (this.markup); - this._bin.child.add_child(this.label); - } - - Main.layoutManager.uiGroup.add_child(this._bin); - Main.layoutManager.uiGroup.set_child_above_sibling(this._bin, null); - } else if (this.custom) { - this._bin.child = this.custom; - } else { - if (this._bin.child.icon) - this._bin.child.icon.destroy(); - - if (this.gicon) { - this._bin.child.icon = new St.Icon({gicon: this.gicon}); - this._bin.child.insert_child_at_index(this._bin.child.icon, 0); - } - - this.label.clutter_text.text = this.markup || this.text; - this.label.clutter_text.use_markup = (this.markup); - } - - // Position tooltip - let [x, y] = this.parent.get_transformed_position(); - x = (x + (this.parent.width / 2)) - Math.round(this._bin.width / 2); - - x += this.x_offset; - y += this.y_offset; - - // Show tooltip - if (this._showing) { - this._bin.ease({ - x: x, - y: y, - time: 0.15, - transition: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } else { - this._bin.set_position(x, y); - this._bin.ease({ - opacity: 232, - time: 0.15, - transition: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - - this._showing = true; - } - - // Enable browse mode - TOOLTIP_BROWSE_MODE = true; - - if (TOOLTIP_BROWSE_ID) { - GLib.source_remove(TOOLTIP_BROWSE_ID); - TOOLTIP_BROWSE_ID = 0; - } - - if (this._hoverTimeoutId) { - GLib.source_remove(this._hoverTimeoutId); - this._hoverTimeoutId = 0; - } - } - - _hide() { - if (this._bin) { - this._bin.ease({ - opacity: 0, - time: 0.10, - transition: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => { - Main.layoutManager.uiGroup.remove_actor(this._bin); - - if (this.custom) - this._bin.remove_child(this.custom); - - this._bin.destroy(); - this._bin = null; - }, - }); - } - - TOOLTIP_BROWSE_ID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => { - TOOLTIP_BROWSE_MODE = false; - TOOLTIP_BROWSE_ID = 0; - return false; - }); - - if (this._hoverTimeoutId) { - GLib.source_remove(this._hoverTimeoutId); - this._hoverTimeoutId = 0; - } - - this._showing = false; - this._hoverTimeoutId = 0; - } - - _onHover() { - if (this.parent.hover) { - if (!this._hoverTimeoutId) { - if (this._showing) { - this._show(); - } else { - this._hoverTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - (TOOLTIP_BROWSE_MODE) ? 60 : 500, - () => { - this._show(); - this._hoverTimeoutId = 0; - return false; - } - ); - } - } - } else { - this._hide(); - } - } - - destroy() { - this.parent.disconnect(this._destroyId); - this.parent.disconnect(this._hoverId); - this.parent.disconnect(this._buttonPressEventId); - - if (this.custom) - this.custom.destroy(); - - if (this._bin) { - Main.layoutManager.uiGroup.remove_actor(this._bin); - this._bin.destroy(); - } - - if (TOOLTIP_BROWSE_ID) { - GLib.source_remove(TOOLTIP_BROWSE_ID); - TOOLTIP_BROWSE_ID = 0; - } - - if (this._hoverTimeoutId) { - GLib.source_remove(this._hoverTimeoutId); - this._hoverTimeoutId = 0; - } - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/utils.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/utils.js deleted file mode 100755 index beea4624..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/shell/utils.js +++ /dev/null @@ -1,283 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Gtk from 'gi://Gtk'; - -import Config from '../config.js'; - -let St = null; // St is not available for prefs.js importing this file. -try { - St = (await import('gi://St')).default; -} catch (e) { } - - -/** - * Get a themed icon, using fallbacks from GSConnect's GResource when necessary. - * - * @param {string} name - A themed icon name - * @return {Gio.Icon} A themed icon - */ -export function getIcon(name) { - if (getIcon._resource === undefined) { - // Setup the desktop icons - const settings = St.Settings.get(); - getIcon._desktop = new Gtk.IconTheme(); - getIcon._desktop.set_theme_name(settings.gtk_icon_theme); - settings.connect('notify::gtk-icon-theme', (settings_, key_) => { - getIcon._desktop.set_theme_name(settings_.gtk_icon_theme); - }); - - // Preload our fallbacks - const iconPath = 'resource://org/gnome/Shell/Extensions/GSConnect/icons'; - const iconNames = [ - 'org.gnome.Shell.Extensions.GSConnect', - 'org.gnome.Shell.Extensions.GSConnect-symbolic', - 'computer-symbolic', - 'laptop-symbolic', - 'smartphone-symbolic', - 'tablet-symbolic', - 'tv-symbolic', - 'phonelink-ring-symbolic', - 'sms-symbolic', - ]; - - getIcon._resource = {}; - - for (const iconName of iconNames) { - getIcon._resource[iconName] = new Gio.FileIcon({ - file: Gio.File.new_for_uri(`${iconPath}/${iconName}.svg`), - }); - } - } - - // Check the desktop icon theme - if (getIcon._desktop.has_icon(name)) - return new Gio.ThemedIcon({name: name}); - - // Check our GResource - if (getIcon._resource[name] !== undefined) - return getIcon._resource[name]; - - // Fallback to hoping it's in the theme somewhere - return new Gio.ThemedIcon({name: name}); -} - - -/** - * Get the contents of a GResource file, replacing `@PACKAGE_DATADIR@` where - * necessary. - * - * @param {string} relativePath - A path relative to GSConnect's resource path - * @return {string} The file contents as a string - */ -function getResource(relativePath) { - try { - const bytes = Gio.resources_lookup_data( - GLib.build_filenamev([Config.APP_PATH, relativePath]), - Gio.ResourceLookupFlags.NONE - ); - - const source = new TextDecoder().decode(bytes.toArray()); - - return source.replace('@PACKAGE_DATADIR@', Config.PACKAGE_DATADIR); - } catch (e) { - logError(e, 'GSConnect'); - return null; - } -} - - -/** - * Install file contents, to an absolute directory path. - * - * @param {string} dirname - An absolute directory path - * @param {string} basename - The file name - * @param {string} contents - The file contents - * @return {boolean} A success boolean - */ -function _installFile(dirname, basename, contents) { - try { - const filename = GLib.build_filenamev([dirname, basename]); - GLib.mkdir_with_parents(dirname, 0o755); - - return GLib.file_set_contents(filename, contents); - } catch (e) { - logError(e, 'GSConnect'); - return false; - } -} - -/** - * Install file contents from a GResource, to an absolute directory path. - * - * @param {string} dirname - An absolute directory path - * @param {string} basename - The file name - * @param {string} relativePath - A path relative to GSConnect's resource path - * @return {boolean} A success boolean - */ -function _installResource(dirname, basename, relativePath) { - try { - const contents = getResource(relativePath); - - return _installFile(dirname, basename, contents); - } catch (e) { - logError(e, 'GSConnect'); - return false; - } -} - -/** - * Use Gio.File to ensure a file's executable bits are set. - * - * @param {string} filepath - An absolute path to a file - * @returns {boolean} - True if the file already was, or is now, executable - */ -function _setExecutable(filepath) { - try { - const file = Gio.File.new_for_path(filepath); - const finfo = file.query_info( - `${Gio.FILE_ATTRIBUTE_STANDARD_TYPE},${Gio.FILE_ATTRIBUTE_UNIX_MODE}`, - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null); - - if (!finfo.has_attribute(Gio.FILE_ATTRIBUTE_UNIX_MODE)) - return false; - - const mode = finfo.get_attribute_uint32( - Gio.FILE_ATTRIBUTE_UNIX_MODE); - const new_mode = (mode | 0o111); - if (mode === new_mode) - return true; - - return file.set_attribute_uint32( - Gio.FILE_ATTRIBUTE_UNIX_MODE, - new_mode, - Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, - null); - } catch (e) { - logError(e, 'GSConnect'); - return false; - } -} - -/** - * Ensure critical files in the extension directory have the - * correct permissions. - */ -export function ensurePermissions() { - if (Config.IS_USER) { - const executableFiles = [ - 'gsconnect-preferences', - 'service/daemon.js', - 'service/nativeMessagingHost.js', - ]; - for (const file of executableFiles) - _setExecutable(GLib.build_filenamev([Config.PACKAGE_DATADIR, file])); - } -} - -/** - * Install the files necessary for the GSConnect service to run. - */ -export function installService() { - const settings = new Gio.Settings({ - settings_schema: Config.GSCHEMA.lookup( - 'org.gnome.Shell.Extensions.GSConnect', - null - ), - path: '/org/gnome/shell/extensions/gsconnect/', - }); - - const confDir = GLib.get_user_config_dir(); - const dataDir = GLib.get_user_data_dir(); - const homeDir = GLib.get_home_dir(); - - // DBus Service - const dbusDir = GLib.build_filenamev([dataDir, 'dbus-1', 'services']); - const dbusFile = `${Config.APP_ID}.service`; - - // Desktop Entry - const appDir = GLib.build_filenamev([dataDir, 'applications']); - const appFile = `${Config.APP_ID}.desktop`; - const appPrefsFile = `${Config.APP_ID}.Preferences.desktop`; - - // Application Icon - const iconDir = GLib.build_filenamev([dataDir, 'icons', 'hicolor', 'scalable', 'apps']); - const iconFull = `${Config.APP_ID}.svg`; - const iconSym = `${Config.APP_ID}-symbolic.svg`; - - // File Manager Extensions - const fileManagers = [ - [`${dataDir}/nautilus-python/extensions`, 'nautilus-gsconnect.py'], - [`${dataDir}/nemo-python/extensions`, 'nemo-gsconnect.py'], - ]; - - // WebExtension Manifests - const manifestFile = 'org.gnome.shell.extensions.gsconnect.json'; - const google = getResource(`webextension/${manifestFile}.google.in`); - const mozilla = getResource(`webextension/${manifestFile}.mozilla.in`); - const manifests = [ - [`${confDir}/chromium/NativeMessagingHosts/`, google], - [`${confDir}/google-chrome/NativeMessagingHosts/`, google], - [`${confDir}/google-chrome-beta/NativeMessagingHosts/`, google], - [`${confDir}/google-chrome-unstable/NativeMessagingHosts/`, google], - [`${confDir}/BraveSoftware/Brave-Browser/NativeMessagingHosts/`, google], - [`${confDir}/BraveSoftware/Brave-Browser-Beta/NativeMessagingHosts/`, google], - [`${confDir}/BraveSoftware/Brave-Browser-Nightly/NativeMessagingHosts/`, google], - [`${homeDir}/.mozilla/native-messaging-hosts/`, mozilla], - [`${homeDir}/.config/microsoft-edge-dev/NativeMessagingHosts`, google], - [`${homeDir}/.config/microsoft-edge-beta/NativeMessagingHosts`, google], - ]; - - // If running as a user extension, ensure the DBus service, desktop entry, - // file manager scripts, and WebExtension manifests are installed. - if (Config.IS_USER) { - // DBus Service - if (!_installResource(dbusDir, dbusFile, `${dbusFile}.in`)) - throw Error('GSConnect: Failed to install DBus Service'); - - // Desktop Entries - _installResource(appDir, appFile, appFile); - _installResource(appDir, appPrefsFile, appPrefsFile); - - // Application Icon - _installResource(iconDir, iconFull, `icons/${iconFull}`); - _installResource(iconDir, iconSym, `icons/${iconSym}`); - - // File Manager Extensions - const target = `${Config.PACKAGE_DATADIR}/nautilus-gsconnect.py`; - - for (const [dir, name] of fileManagers) { - const script = Gio.File.new_for_path(GLib.build_filenamev([dir, name])); - - if (!script.query_exists(null)) { - GLib.mkdir_with_parents(dir, 0o755); - script.make_symbolic_link(target, null); - } - } - - // WebExtension Manifests - if (settings.get_boolean('create-native-messaging-hosts')) { - for (const [dirname, contents] of manifests) - _installFile(dirname, manifestFile, contents); - } - - // Otherwise, if running as a system extension, ensure anything previously - // installed when running as a user extension is removed. - } else { - GLib.unlink(GLib.build_filenamev([dbusDir, dbusFile])); - GLib.unlink(GLib.build_filenamev([appDir, appFile])); - GLib.unlink(GLib.build_filenamev([appDir, appPrefsFile])); - GLib.unlink(GLib.build_filenamev([iconDir, iconFull])); - GLib.unlink(GLib.build_filenamev([iconDir, iconSym])); - - for (const [dir, name] of fileManagers) - GLib.unlink(GLib.build_filenamev([dir, name])); - - for (const manifest of manifests) - GLib.unlink(GLib.build_filenamev([manifest[0], manifestFile])); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/stylesheet.css deleted file mode 100755 index ea455d0e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/stylesheet.css +++ /dev/null @@ -1,127 +0,0 @@ -/* - * SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -/* Device Menu - -PopupMenu.PopupMenuSection.gsconnect-device-section - PopupMenu.PopupMenuSection.gsconnect-device-menu - PopupMenu.PopupSeparatorMenuItem - StLabel.gsconnect-device-name - StBoxLayout.gsconnect-device-battery - PopupMenu.PopupMenuSection - StBoxLayout.gsconnect-list-box - StBoxLayout (Submenu Container) -*/ -.gsconnect-device-section { -} - -/* Title Bar */ -.gsconnect-device-name { - font-weight: bold; -} - -.gsconnect-device-menu .popup-separator-menu-item { - margin-left: 0; - margin-right: 0; -} - -/* Battery Widget */ -.gsconnect-device-battery { - spacing: 3px; -} - -.gsconnect-device-battery StLabel { - font-size: 0.75em; -} - -.gsconnect-device-battery StIcon { - icon-size: 16px; -} - -/* Signal Strength Widget */ -.gsconnect-device-signal-strength { - spacing: 3px; -} - -.gsconnect-device-signal-strength StLabel { - font-size: 0.75em; -} - -.gsconnect-device-signal-strength StIcon { - icon-size: 16px; -} - -/* List Box */ -.gsconnect-list-box { -} - - -/* Device Panel Indicator - -PanelMenu.Button.gsconnect-device-indicator - PopupMenu.PopupMenu - PopupMenu.PopupMenuSection.gsconnect-device-menu - PopupMenu.PopupSeparatorMenuItem - StLabel.gsconnect-device-name - StBoxLayout.gsconnect-device-battery - PopupMenu.PopupMenuSection - StBoxLayout.gsconnect-icon-box - StBoxLayout (Submenu Container) - */ -.gsconnect-device-indicator { - -st-icon-style: symbolic; -} - -/* Icon Box */ -.gsconnect-icon-box { - margin: 0em 2em 0.5em; - spacing: 6px; -} - -.gsconnect-icon-button { - border-radius: 1em; - padding: 0.5em; -} - -.gsconnect-icon-button:hover, .gsconnect-icon-button:focus { - background-color: rgba(255, 255, 255, 0.125); -} - -.gsconnect-icon-button StIcon { - icon-size: 1em; -} - - -/* Tooltip - -StBin.gsconnect-tooltip (inherits from .osd-window) - StBoxLayout || [ Custom ClutterActor ] - StIcon - StLabel -*/ -.gsconnect-tooltip { - border-radius: 3px; - min-width: 0; - min-height: 0; - padding: 6px; -} - -.gsconnect-tooltip > StBoxLayout { - spacing: 6px; -} - -.gsconnect-tooltip StIcon { - icon-size: 16px; -} - -.gsconnect-tooltip StLabel { - font-weight: normal; - text-align: left; -} - -.gsconnect-tooltip StLabel:rtl { - text-align: right; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/utils/remote.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/utils/remote.js deleted file mode 100755 index 44760cd2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/utils/remote.js +++ /dev/null @@ -1,516 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -const SERVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect'; -const SERVICE_PATH = '/org/gnome/Shell/Extensions/GSConnect'; -const DEVICE_NAME = 'org.gnome.Shell.Extensions.GSConnect.Device'; - - -const _PROPERTIES = { - 'Connected': 'connected', - 'EncryptionInfo': 'encryption-info', - 'IconName': 'icon-name', - 'Id': 'id', - 'Name': 'name', - 'Paired': 'paired', - 'Type': 'type', -}; - - -function _proxyInit(proxy, cancellable = null) { - if (proxy.__initialized !== undefined) - return Promise.resolve(); - - return new Promise((resolve, reject) => { - proxy.init_async( - GLib.PRIORITY_DEFAULT, - cancellable, - (proxy, res) => { - try { - proxy.init_finish(res); - proxy.__initialized = true; - resolve(); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - reject(e); - } - } - ); - }); -} - - -/** - * A simple proxy wrapper for devices exported over DBus. - */ -export const Device = GObject.registerClass({ - GTypeName: 'GSConnectRemoteDevice', - Implements: [Gio.DBusInterface], - Properties: { - 'connected': GObject.ParamSpec.boolean( - 'connected', - 'Connected', - 'Whether the device is connected', - GObject.ParamFlags.READABLE, - null - ), - 'encryption-info': GObject.ParamSpec.string( - 'encryption-info', - 'Encryption Info', - 'A formatted string with the local and remote fingerprints', - GObject.ParamFlags.READABLE, - null - ), - 'icon-name': GObject.ParamSpec.string( - 'icon-name', - 'Icon Name', - 'Icon name representing the device', - GObject.ParamFlags.READABLE, - null - ), - 'id': GObject.ParamSpec.string( - 'id', - 'deviceId', - 'The device hostname or other unique id', - GObject.ParamFlags.READABLE, - '' - ), - 'name': GObject.ParamSpec.string( - 'name', - 'deviceName', - 'The device name', - GObject.ParamFlags.READABLE, - null - ), - 'paired': GObject.ParamSpec.boolean( - 'paired', - 'Paired', - 'Whether the device is paired', - GObject.ParamFlags.READABLE, - null - ), - 'type': GObject.ParamSpec.string( - 'type', - 'deviceType', - 'The device type', - GObject.ParamFlags.READABLE, - null - ), - }, -}, class Device extends Gio.DBusProxy { - - _init(service, object_path) { - this._service = service; - - super._init({ - g_connection: service.g_connection, - g_name: SERVICE_NAME, - g_object_path: object_path, - g_interface_name: DEVICE_NAME, - }); - } - - vfunc_g_properties_changed(changed, invalidated) { - try { - for (const name in changed.deepUnpack()) - this.notify(_PROPERTIES[name]); - } catch (e) { - logError(e); - } - } - - _get(name, fallback = null) { - try { - return this.get_cached_property(name).unpack(); - } catch (e) { - return fallback; - } - } - - get connected() { - return this._get('Connected', false); - } - - get encryption_info() { - return this._get('EncryptionInfo', ''); - } - - get icon_name() { - return this._get('IconName', 'computer'); - } - - get id() { - return this._get('Id', '0'); - } - - get name() { - return this._get('Name', 'Unknown'); - } - - get paired() { - return this._get('Paired', false); - } - - get service() { - return this._service; - } - - get type() { - return this._get('Type', 'desktop'); - } - - async start() { - try { - await _proxyInit(this); - - // For GActions & GMenu we pass the service's name owner to avoid - // any mixup with instances. - this.action_group = Gio.DBusActionGroup.get( - this.g_connection, - this.service.g_name_owner, - this.g_object_path - ); - - this.menu = Gio.DBusMenuModel.get( - this.g_connection, - this.service.g_name_owner, - this.g_object_path - ); - - // Poke the GMenu to ensure it's ready for us - await new Promise((resolve, reject) => { - this.g_connection.call( - SERVICE_NAME, - this.g_object_path, - 'org.gtk.Menus', - 'Start', - new GLib.Variant('(au)', [[0]]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (proxy, res) => { - try { - resolve(proxy.call_finish(res)); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - reject(e); - } - } - ); - }); - } catch (e) { - this.destroy(); - throw e; - } - } - - destroy() { - GObject.signal_handlers_destroy(this); - } -}); - - -/** - * A simple proxy wrapper for the GSConnect service. - */ -export const Service = GObject.registerClass({ - GTypeName: 'GSConnectRemoteService', - Implements: [Gio.DBusInterface], - Properties: { - 'active': GObject.ParamSpec.boolean( - 'active', - 'Active', - 'Whether the service is active', - GObject.ParamFlags.READABLE, - false - ), - }, - Signals: { - 'device-added': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [Device.$gtype], - }, - 'device-removed': { - flags: GObject.SignalFlags.RUN_FIRST, - param_types: [Device.$gtype], - }, - }, -}, class Service extends Gio.DBusProxy { - - _init() { - super._init({ - g_bus_type: Gio.BusType.SESSION, - g_name: SERVICE_NAME, - g_object_path: SERVICE_PATH, - g_interface_name: 'org.freedesktop.DBus.ObjectManager', - g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START_AT_CONSTRUCTION, - }); - - this._active = false; - this._devices = new Map(); - this._starting = false; - - // Watch the service - this._nameOwnerChangedId = this.connect( - 'notify::g-name-owner', - this._onNameOwnerChanged.bind(this) - ); - } - - get active() { - return this._active; - } - - get devices() { - return Array.from(this._devices.values()); - } - - vfunc_g_signal(sender_name, signal_name, parameters) { - try { - // Don't emit signals until the ObjectManager has started - if (!this.active) - return; - - parameters = parameters.deepUnpack(); - - switch (true) { - case (signal_name === 'InterfacesAdded'): - this._onInterfacesAdded(...parameters); - break; - - case (signal_name === 'InterfacesRemoved'): - this._onInterfacesRemoved(...parameters); - break; - } - } catch (e) { - logError(e); - } - } - - /** - * org.freedesktop.DBus.ObjectManager.InterfacesAdded - * - * @param {string} object_path - Path interfaces have been added to - * @param {Object} interfaces - A dictionary of interface objects - */ - async _onInterfacesAdded(object_path, interfaces) { - try { - // An empty list means only the object has been added - if (Object.values(interfaces).length === 0) - return; - - // Skip existing proxies - if (this._devices.has(object_path)) - return; - - // Create a proxy - const device = new Device(this, object_path); - await device.start(); - - // Hold the proxy and emit ::device-added - this._devices.set(object_path, device); - this.emit('device-added', device); - } catch (e) { - logError(e, object_path); - } - } - - /** - * org.freedesktop.DBus.ObjectManager.InterfacesRemoved - * - * @param {string} object_path - Path interfaces have been removed from - * @param {string[]} interfaces - List of interface names removed - */ - _onInterfacesRemoved(object_path, interfaces) { - try { - // An empty interface list means the object is being removed - if (interfaces.length === 0) - return; - - // Get the proxy - const device = this._devices.get(object_path); - - if (device === undefined) - return; - - // Release the proxy and emit ::device-removed - this._devices.delete(object_path); - this.emit('device-removed', device); - - // Destroy the device and force disposal - device.destroy(); - } catch (e) { - logError(e, object_path); - } - } - - async _addDevices() { - const objects = await new Promise((resolve, reject) => { - this.call( - 'GetManagedObjects', - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (proxy, res) => { - try { - const variant = proxy.call_finish(res); - resolve(variant.deepUnpack()[0]); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - reject(e); - } - } - ); - }); - - for (const [object_path, object] of Object.entries(objects)) - await this._onInterfacesAdded(object_path, object); - } - - _clearDevices() { - for (const [object_path, device] of this._devices) { - this._devices.delete(object_path); - this.emit('device-removed', device); - device.destroy(); - } - } - - async _onNameOwnerChanged() { - try { - // If the service stopped, remove each device and mark it inactive - if (this.g_name_owner === null) { - this._clearDevices(); - - this._active = false; - this.notify('active'); - - // If the service started, mark it active and add each device - } else { - this._active = true; - this.notify('active'); - - await this._addDevices(); - } - } catch (e) { - logError(e); - } - } - - /** - * Reload all devices without affecting the remote service. This amounts to - * removing and adding each device while emitting the appropriate signals. - */ - async reload() { - try { - if (this._starting === false) { - this._starting = true; - - this._clearDevices(); - await _proxyInit(this); - await this._onNameOwnerChanged(); - - this._starting = false; - } - } catch (e) { - this._starting = false; - throw e; - } - } - - /** - * Start the service - */ - async start() { - try { - if (this._starting === false && this.active === false) { - this._starting = true; - - await _proxyInit(this); - await this._onNameOwnerChanged(); - - // Activate the service if it's not already running - if (!this.active) { - await new Promise((resolve, reject) => { - this.g_connection.call( - SERVICE_NAME, - SERVICE_PATH, - 'org.freedesktop.Application', - 'Activate', - GLib.Variant.new('(a{sv})', [{}]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - (proxy, res) => { - try { - resolve(proxy.call_finish(res)); - } catch (e) { - Gio.DBusError.strip_remote_error(e); - reject(e); - } - } - ); - }); - } - - this._starting = false; - } - } catch (e) { - this._starting = false; - throw e; - } - } - - /** - * Stop the service - */ - stop() { - if (this.active) - this.activate_action('quit'); - } - - activate_action(name, parameter = null) { - try { - const paramArray = []; - - if (parameter instanceof GLib.Variant) - paramArray[0] = parameter; - - const connection = this.g_connection || Gio.DBus.session; - - connection.call( - SERVICE_NAME, - SERVICE_PATH, - 'org.freedesktop.Application', - 'ActivateAction', - GLib.Variant.new('(sava{sv})', [name, paramArray, {}]), - null, - Gio.DBusCallFlags.NONE, - -1, - null, - null - ); - } catch (e) { - logError(e); - } - } - - destroy() { - if (this._nameOwnerChangedId > 0) { - this.disconnect(this._nameOwnerChangedId); - this._nameOwnerChangedId = 0; - - this._clearDevices(); - this._active = false; - - GObject.signal_handlers_destroy(this); - } - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/utils/setup.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/utils/setup.js deleted file mode 100755 index eef58dc9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/utils/setup.js +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - -import Gettext from 'gettext'; - -import Config from '../config.js'; - - -/** - * Initialise and setup Gettext. - */ -export function setupGettext() { - // Init Gettext - String.prototype.format = imports.format.format; - Gettext.bindtextdomain(Config.APP_ID, Config.PACKAGE_LOCALEDIR); - globalThis._ = GLib.dgettext.bind(null, Config.APP_ID); - globalThis.ngettext = GLib.dngettext.bind(null, Config.APP_ID); -} - -/** - * Initialise and setup Config, GResources and GSchema. - * @param {string} extensionPath - The absolute path to the extension directory - */ -export default function setup(extensionPath) { - // Ensure config.js is setup properly - Config.PACKAGE_DATADIR = extensionPath; - const userDir = GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']); - - if (Config.PACKAGE_DATADIR.startsWith(userDir)) { - Config.IS_USER = true; - - Config.GSETTINGS_SCHEMA_DIR = `${Config.PACKAGE_DATADIR}/schemas`; - Config.PACKAGE_LOCALEDIR = `${Config.PACKAGE_DATADIR}/locale`; - } - - // Init GResources - Gio.Resource.load( - GLib.build_filenamev([Config.PACKAGE_DATADIR, `${Config.APP_ID}.gresource`]) - )._register(); - - // Init GSchema - Config.GSCHEMA = Gio.SettingsSchemaSource.new_from_directory( - Config.GSETTINGS_SCHEMA_DIR, - Gio.SettingsSchemaSource.get_default(), - false - ); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/wl_clipboard.js b/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/wl_clipboard.js deleted file mode 100755 index 8e1dedd9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/gsconnect@andyholmes.github.io/wl_clipboard.js +++ /dev/null @@ -1,296 +0,0 @@ -// SPDX-FileCopyrightText: JingMatrix https://github.com/JingMatrix -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import Gio from 'gi://Gio'; -import GjsPrivate from 'gi://GjsPrivate'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -// laucher for wl-clipboard -const launcher = new Gio.SubprocessLauncher({ - flags: Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_MERGE, -}); - -/* - * DBus Interface Info - */ -const DBUS_NAME = 'org.gnome.Shell.Extensions.GSConnect.Clipboard'; -const DBUS_PATH = '/org/gnome/Shell/Extensions/GSConnect/Clipboard'; -const DBUS_NODE = Gio.DBusNodeInfo.new_for_xml(` -<node> - <interface name="org.gnome.Shell.Extensions.GSConnect.Clipboard"> - <!-- Methods --> - <method name="GetMimetypes"> - <arg direction="out" type="as" name="mimetypes"/> - </method> - <method name="GetText"> - <arg direction="out" type="s" name="text"/> - </method> - <method name="SetText"> - <arg direction="in" type="s" name="text"/> - </method> - - <!-- Signals --> - <signal name="OwnerChange"/> - </interface> -</node> -`); -const DBUS_INFO = DBUS_NODE.lookup_interface(DBUS_NAME); - -/* - * Text Mimetypes - */ -const TEXT_MIMETYPES = [ - 'text/plain;charset=utf-8', - 'UTF8_STRING', - 'text/plain', - 'STRING', -]; - -/* GSConnectClipboardPortal: - * - * A simple clipboard portal, especially useful on Wayland where GtkClipboard - * doesn't work in the background. - */ -export const Clipboard = GObject.registerClass( - { - GTypeName: 'GSConnectShellClipboard', - }, - class GSConnectShellClipboard extends GjsPrivate.DBusImplementation { - _init() { - super._init({ - g_interface_info: DBUS_INFO, - }); - - this._transferring = false; - - this.watcher = Gio.Subprocess.new([ - 'wl-paste', - '-w', - 'dbus-send', - DBUS_PATH, - '--dest=' + DBUS_NAME, - DBUS_NAME + '.OwnerChange', - ], Gio.SubprocessFlags.NONE); - - // Prepare DBus interface - this._handleMethodCallId = this.connect( - 'handle-method-call', - this._onHandleMethodCall.bind(this) - ); - - this._nameId = Gio.DBus.own_name( - Gio.BusType.SESSION, - DBUS_NAME, - Gio.BusNameOwnerFlags.NONE, - this._onBusAcquired.bind(this), - null, - this._onNameLost.bind(this) - ); - } - - _onBusAcquired(connection, name) { - try { - this.export(connection, DBUS_PATH); - } catch (e) { - logError(e); - } - } - - _onNameLost(connection, name) { - try { - this.unexport(); - } catch (e) { - logError(e); - } - } - - async _onHandleMethodCall(iface, name, parameters, invocation) { - let retval; - - try { - const args = parameters.recursiveUnpack(); - - retval = await this[name](...args); - } catch (e) { - if (e instanceof GLib.Error) { - invocation.return_gerror(e); - } else { - if (!e.name.includes('.')) - e.name = `org.gnome.gjs.JSError.${e.name}`; - - invocation.return_dbus_error(e.name, e.message); - } - - return; - } - - if (retval === undefined) - retval = new GLib.Variant('()', []); - - try { - if (!(retval instanceof GLib.Variant)) { - const args = DBUS_INFO.lookup_method(name).out_args; - retval = new GLib.Variant( - `(${args.map((arg) => arg.signature).join('')})`, - args.length === 1 ? [retval] : retval - ); - } - - invocation.return_value(retval); - - // Without a response, the client will wait for timeout - } catch (e) { - invocation.return_dbus_error( - 'org.gnome.gjs.JSError.ValueError', - 'Service implementation returned an incorrect value type' - ); - } - } - - /** - * Get the available mimetypes of the current clipboard content - * - * @return {Promise<string[]>} A list of mime-types - */ - - GetMimetypes() { - return new Promise((resolve, reject) => { - const proc = launcher.spawnv([ - 'wl-paste', - '--list-types', - '-n', - ]); - proc.communicate_utf8_async(null, null, (proc, res) => { - try { - const [, stdout, stderr] = - proc.communicate_utf8_finish(res); - if (proc.get_successful()) - resolve(stdout.trim().split('\n')); - else - logError(stderr); - - } catch (e) { - reject(e); - } - }); - }); - } - - /** - * Get the text content of the clipboard - * - * @return {Promise<string>} Text content of the clipboard - */ - GetText() { - return new Promise((resolve, reject) => { - this.GetMimetypes().then((mimetypes) => { - const mimetype = TEXT_MIMETYPES.find((type) => - mimetypes.includes(type) - ); - - if (mimetype !== undefined) { - const proc = launcher.spawnv(['wl-paste', '-n']); - proc.communicate_utf8_async(null, null, (proc, res) => { - try { - const [, stdout, stderr] = - proc.communicate_utf8_finish(res); - if (proc.get_successful()) - resolve(stdout); - else - logError(stderr); - - } catch (e) { - reject(e); - } - }); - } else { - reject(new Error('text not available')); - } - }); - }); - } - - /** - * Set the text content of the clipboard - * - * @param {string} text - text content to set - * @return {Promise} A promise for the operation - */ - SetText(text) { - return new Promise((resolve, reject) => { - try { - if (typeof text !== 'string') { - throw new Gio.DBusError({ - code: Gio.DBusError.INVALID_ARGS, - message: 'expected string', - }); - } - - launcher.spawnv(['wl-copy', text]); - resolve(); - } catch (e) { - reject(e); - } - }); - } - - - - destroy() { - if (this._nameId > 0) { - Gio.bus_unown_name(this._nameId); - this._nameId = 0; - } - - if (this._handleMethodCallId > 0) { - this.disconnect(this._handleMethodCallId); - this._handleMethodCallId = 0; - this.unexport(); - } - if (this.watcher) - this.watcher.force_exit(); - - } - } -); - -let _portal = null; -let _portalId = 0; - -/** - * Watch for the service to start and export the clipboard portal when it does. - */ -export function watchService() { - if (_portalId > 0) - return; - - _portalId = Gio.bus_watch_name( - Gio.BusType.SESSION, - 'org.gnome.Shell.Extensions.GSConnect', - Gio.BusNameWatcherFlags.NONE, - () => { - if (_portal === null) - _portal = new Clipboard(); - }, - () => { - if (_portal !== null) { - _portal.destroy(); - _portal = null; - } - } - ); -} - -/** - * Stop watching the service and export the portal if currently running. - */ -export function unwatchService() { - if (_portalId > 0) { - Gio.bus_unwatch_name(_portalId); - _portalId = 0; - } -} - -// vim:tabstop=2:shiftwidth=2:expandtab diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/CHANGELOG.md b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/CHANGELOG.md deleted file mode 100755 index e9b2800d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/CHANGELOG.md +++ /dev/null @@ -1,528 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -We go to the next version after each release on the -[GNOME Shell Extensions website](https://extensions.gnome.org/). - -## [Unreleased] - -## [28.0.0 Lear] - 2024-03-06 - -### Added - -- Buy Me a Coffee donation link. -- GNOME Shell 46 Support. -- Option to maximize windows on creation by [@droserasprout](https://gitlab.gnome.org/droserasprout). - -### Fixed - -- The world clock visibility coming back after reboot or install change. - -### Removed - -- Window Picker Shell Theme Override. -- Search Shell Theme Override. -- Workspace Animation Shell Theme Override. -- Dash Background Shell Theme Override. - -## [27.0.0 Durer] - 2023-09-14 - -### Changed - -- The world clocks visibility from CSS to JS. - -### Added - -- "Almost none" option to animation speed feature (GNOME Shell 45). -- GNOME Shell 45 Support. -- Japanese Translation by [@gnuey56](https://gitlab.gnome.org/gnuey56). - -### Removed - -- Activities button icon feature (GNOME Shell 45). -- App menu indicator (GNOME Shell 45). - -## [26.0.0 Rosa] - 2023-08-07 - -### Fixed - -- Remove not defined. - -## [25.0.0 Rosa] - 2023-08-07 - -### Changed - -- The behavior of the panel is shown only in the overview. - Rather than sliding in from the top, it is now rendered behind the workspaces - by [Schneegans](https://gitlab.gnome.org/Schneegans). - -### Fixed - -- a11y error in GNOME Shell mobile. -- Activities button error in GNOME Shell mobile. -- Marked as an urgent signal for window demand attention focus feature. -- Panel flickering when its position is at the bottom. -- `.set_icon_size` is not a function error (Date Menu). -- Unwanted padding on the disabled power icon. -- Unwanted shadow for workspace in the app grid. - -### Added - -- Dash app running visibility. -- Disable the overlay key. -- EGO donations. -- Workspace peek (GNOME Shell 42 and higher). - -### Removed - -- GNOME Shell support (3.36, 3.38, 40 and 41 no longer getting new features). - -## [24.0.0 Hals] - 2023-03-01 - -### Changed - -- Window preview close button for super minimal profile (to disabled). - -### Added - -- GNOME Shell 44 support. -- Transparent dash background for shell theme override (GNOME Shell 4x only). - -## [23.0.0 Goya] - 2023-02-10 - -### Changed - -- Clock menu offset maximum to 20. -- Fastest animation speed (twice as fast as before). - -### Fixed - -- App menu label visibility compatibility issue with open whether extension. -- Hidden workspace switcher padding in overview. -- Keep the clock menu position when another widget is added to the panel. -- Looking Glass API conflicts with the "Dash to Panel" extension. -- Looking Glass error when primary monitor doesn't exist. -- Window preview gap when window picker close button is disabled. -- Workspace boxes top margin in the app grid when the search entry is disabled. -- Italian translation by [@svityboy](https://gitlab.gnome.org/svityboy). - -### Added - -- More dash icon size (16px, 22px, 24px, 40px and 56px). -- Overview spacing size. -- Screen recording indicator visibility. -- Screen sharing indicator visibility. -- Switcher popup delay by [@koplo199](https://gitlab.gnome.org/koplo199). - -## [22.0.0 Millet] - 2022-09-10 - -### Fixed - -- Dash app button visibility height. -- Looking glass error after unlock. - -### Added - -- App menu label visibility. -- GNOME Shell 43 support. -- Quick settings menu visibility. - -### Removed - -- Aggregate menu for GNOME Shell 43 and higher. - -## [21.0.0 Reynolds] - 2022-08-06 - -### Changed - -- Prefs compatibility layer checking to GTK and Adw instead of GNOME Shell version. - -### Fixed - -- Application button visibility in Ubuntu 22.04. -- Prefs window size for scaled displays. -- Prefs window size for small displays in GNOME Shell 42. -- Racy prefs window size. -- Window caption going out of display area when dash is disabled in GNOME Shell 40 and higher. -- Russian translation by [@librusekus35790](https://gitlab.gnome.org/librusekus35790). -- Spanish translation by [@Luci](https://gitlab.gnome.org/Luci). - -### Added - -- Alt-Tab window preview icon size. -- Alt-Tab window preview size. -- Alt-Tab icon size. -- Dash separator visibility. -- Looking glass size by [@AdvendraDeswanta](https://gitlab.gnome.org/AdvendraDeswanta). -- OSD position. -- Take the screenshot button in the window menu visibility. - -### Removed - -- Gesture API for GNOME Shell 40 and higher. -- List box separators for GNOME Shell 40 and 41 (EOS). -- Prefs intro. - -## [20.0.0 Hayez] - 2022-04-01 - -### Fixed - -- Dynamic workspaces getting disabled by workspace popup. -- Flickering panel after Unlock. -- Notification banner position on GNOME Shell 42. -- Window demands attention focus on GNOME Shell 42. -- French translation by [@GeoffreyCoulaud](https://gitlab.gnome.org/GeoffreyCoulaud). -- Italian translation by [@svityboy](https://gitlab.gnome.org/svityboy). - -### Added - -- Events visibility in the clock menu. -- Calendar visibility in the clock menu. -- Dutch translation by [@Vistaus](https://gitlab.gnome.org/Vistaus). - -## [19.0.0 Ancher] - 2022-03-02 - -### Fixed - -- Blurry search entry on GNOME Shell themes with "box-shadow". -- Prefs file chooser recursion. -- SecondaryMonitorDisplay error on GNOME Shell 42. -- Shell theme overrides OSD on GNOME Shell 42. -- Shell theme overrides the workspace switcher on GNOME Shell 42. -- Workspace popup visibility in GNOME Shell 42. - -### Added - -- Libadwaita for GNOME Shell 42 prefs. -- Panel icon size. -- Panel world clock visibility. -- Weather visibility. - -## [18.0.0 Roslin] - 2022-02-12 - -### Fixed - -- GNOME 3.x prefs error. - -## [17.0.0 Roslin] - 2022-02-11 - -### Fixed - -- Emitting panel show when panel is visible. -- Looking glass not showing up. -- Looking glass position on startup when panel is hidden. -- Prefs height going off the screen in small displays. -- Prefs lunching url freeze on Wayland. -- Prefs padding in GNOME Shell 42. -- Prefs UI Improvement by [@muqtxdir](https://gitlab.gnome.org/muqtxdir). -- Startup animation for hiding panel when panel is disabled. -- Type to search when text entry content is replaced with another content. -- Window goes under panel after unlock on Wayland. -- Window picker caption visibility issue on Pop Shell. -- Galician translation by [@frandieguez](https://gitlab.gnome.org/frandieguez). - -### Added - -- Bottom to notification banner position. - -### Removed - -- Panel corner size option for GNOME Shell 42. - -## [16.0.0 Rembrandt] - 2021-11-15 - -### Fixed - -- Animation jump when search entry is disabled and entering app grid. -- Clock menu revealing in lockscreen when the position is left or right. -- Startup status for Ubuntu. -- Workspace switcher visibility in GNOME Shell 41. - -### Removed - -- Hot corner for GNOME Shell 41. -- Hot corner library for all supported Shell versions. - -### Added - -- Double supper to app grid for GNOME Shell 40 and 41. -- Panel corner size when panel is disabled. -- Panel visibility in overview when panel is disabled. -- Prefs window intro. -- Profile selector to the prefs window. -- Ripple box. - -## [15.0.0 Magnetized] - 2021-09-22 - -### Fixed - -- unlock recursion error. - -### Added - -- Hot corner support for GNOME Shell 41. - -## [14.0.0 Magnetized] - 2021-09-22 - -### Changed - -- Repo folder structure to have better organization. - -### Fixed - -- Bottom panel position for multi monitors by [@harshadgavali](https://gitlab.gnome.org/harshadgavali). -- First swipe up in desktop startup status. -- Looking glass position on bottom panel. -- Maximized window gap on Wayland. -- Search entry animation for type to search when search entry is disabled. -- Search entry API to avoid conflicting with other extensions. -- Window picker caption border on disable. -- Window picker disapearing on wayland with shell theme override. -- Galician translation by [@frandieguez](https://gitlab.gnome.org/frandieguez). -- Spanish translation by [@DiegoIvanME](https://gitlab.gnome.org/DiegoIvanME). - -### Removed - -- Donation popover in prefs. -- Hot corner for GNOME Shell 41. - -### Added - -- GNOME Shell 41 support. -- Panel indicator padding size. -- Window picker close button visibility. - -## [13.0.0 Ring] - 2021-08-10 - -### Changed - -- Search button position in prefs window. - -### Fixed - -- Accessing dash in case the original dash has been removed by third party extensions. -- API.monitorGetInfo for "pMonitor is null" error. -- Dropdown align in preferences dialog. -- Startup status blocking shortcut keys. -- Unwanted window demands attention focus. -- Russian translation by [@librusekus35790](https://gitlab.gnome.org/librusekus35790). - -### Removed - -- Settings and Translation library and using ExtensionUtils instead. - -### Added - -- Panel button padding size. -- Panel height. -- Window picker caption visibility. -- Workspace background corner size in overview. -- Workspace wraparound (modified version of WorkspaceSwitcherWrapAround by [@war1025](https://github.com/war1025)). - -## [12.0.0 Queen Red] - 2021-06-29 - -### Changed - -- Lighter background color for switcher list (alt+tab) in override theme. -- Workspace switcher max size now maxed out to 30%. - -### Fixed - -- Combobox scroll issue on GTK4. -- Window demands attention focus notification popup. -- French translation by [@GeoffreyCoulaud](https://gitlab.gnome.org/GeoffreyCoulaud). -- Russian translation by [@librusekus35790](https://gitlab.gnome.org/librusekus35790). - -### Added - -- Always show workspace switcher on dynamic workspaces. -- More descriptions to the preferences dialog. -- Notification banner position. -- Startup status for GNOME Shell 40. -- Workspace animation background color for shell theme override. -- Workspaces visibility in app grid by [@fmuellner](https://gitlab.gnome.org/fmuellner). -- Chinese (Taiwan) translation by [@r0930514](https://gitlab.com/r0930514). - -## [11.0.0 Whisper] - 2021-05-20 - -### Changed - -- App gesture now only works on GNOME 3.36 and 3.38. -- Donation icon to GTK4 non-compatible icon sets. -- Shell theme override is now disabled by default. -- Workspace switcher size for GNOME Shell 40 is now maxed out to 15%. - -### Fixed - -- Gap when panel position is at the bottom and shell override theme happens. -- Panel menu margin when panel is in bottom. -- Window picker icon visibility on drag. -- Workspace switcher size for multi monitor setup. -- Arabic translation by [@AliGalal](https://gitlab.com/AliGalal). -- Chinese translation by [@wsxy162](https://gitlab.com/wsxy162). -- Italian translation by [@l3nn4rt](https://gitlab.com/l3nn4rt). -- Swedish translation by [@MorganAntonsson](https://gitlab.com/MorganAntonsson). - -### Added - -- Activities button icon. -- Dash icon size. -- Window demands attention focus. - -## [10.0.0] - 2021-03-26 - -### Changed - -- Organized prefs UI for icons and behavior. -- Removed quotes and side bar image from prefs UI. - -### Fixed - -- Fake hot corner primary monitor position. -- Horizontal scroll in prefs. -- Primary Monitor Panel Position. -- Arabic translation by [@karem34](https://gitlab.com/karem34). -- Russian translation by [@librusekus35790](https://gitlab.com/librusekus35790). - -### Added - -- Clock menu position. -- Disable animation or change the animation speed. -- Disable applications button in dash. -- Disable app menu icon. -- Disable panel arrow in GNOME 3.36 and 3.38. -- Disable panel notification icon. -- No results found for prefs window. -- Brazilian Portuguese translation by [@Zelling](https://gitlab.com/Zelling). -- Catalan translation by [@juxuanu](https://gitlab.com/juxuanu). -- Galician translation by [@frandieguez](https://gitlab.com/frandieguez). - -## [9.0.0] - 2021-03-06 - -### Changed - -- Prefs interface. - -### Fixed - -- Default value for hot corner on extension disable. -- GNOME Shell 40.beta version. - -### Added - -- Disable power icon. -- Panel position. -- Support to prefs window. - -## [8.0.0] - 2021-02-22 - -### Changed - -- Holding back lonely overview until the final GNOME 40 release. - -### Fixed - -- Dash override theme on GNOME Shell 40 beta. -- Focus for find entry on prefs. -- Search controller for GNOME Shell 40 beta. -- Start search for GNOME Shell 40 beta. -- Workspace switcher enable related to workspace switcher size. -- Nepali translation filename by [@IBA4](https://gitlab.com/IBA4). - -## [7.0.0] - 2021-02-12 - -### Fixed - -- GNOME Shell 40 hidden side by side workspace preview. -- GNOME Shell 40 search padding when panel is disabled. -- Initial prefs window size. - -### Added - -- GNOME Shell 40 window picker icon visibility to the settings. -- GNOME Shell 40 workspace switcher size to the settings. -- Panel corner size to the settings. -- Search feature to the settings. -- Type to Search to the settings. -- Nepali translation by [@IBA4](https://gitlab.com/IBA4). -- Spanish translation by [@oscfdezdz](https://gitlab.com/oscfdezdz). - -## [6.0.0] - 2021-01-29 - -### Fixed - -- GNOME Shell 3.38 extra padding on no workspace switcher. -- GNOME Shell 40 and GTK4 support for prefs. -- GNOME Shell 40 support for search entry. -- GNOME Shell 40 support for workspace switcher. - -## [5.0.0] - 2021-01-05 - -### Added - -- Accessibility Menu visibility to the settings. -- Activities button visibility to the settings. -- App menu visibility to the settings. -- Clock menu visibility to the settings. -- Keyboard Layout visibility to the settings. -- System Menu (Aggregate Menu) visibility to the settings. - -### Changed - -- OSD in settings to "On Screen Display (OSD)". - -### Fixed - -- Hot corner when top panel is visible. -- Padding on no dash. -- Search top padding on no top panel. - -## [4.0.0] 2020-12-25 - -### Added - -- API to decouple all libraries from using GNOME Shell ui directly. -- Automate build process by [@daPhipz](https://gitlab.com/daPhipz). -- CHANGELOG.md file. -- Compatibility layer for API. -- Translation automation script by [@daPhipz](https://gitlab.com/daPhipz). - -### Changed - -- Default settings to enable. -- Displaying error for generate-mo.sh by [@daPhipz](https://gitlab.com/daPhipz). -- German translation by [@M4he](https://gitlab.com/M4he). - -### Fixed - -- Top padding on no search and no top panel. - -## [3.0.0] - 2020-12-21 - -### Added - -- CONTRIBUTING.md file. -- Decoupled library from GNOME Shell ui. -- Extension logo. -- Initial Translations. -- Prefs as extension settings. - -## [2.0.0] - 2020-11-18 - -### Fixed - -- Destroy hot corner on disable. - -## [1.0.0] - 2020-11-15 - -### Added - -- Disable app gesture. -- Disable background menu. -- Hide dash. -- Hide search. -- Hide top panel. -- Hide workspace switcher. -- Hot corner to toggle overview visibility. - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/LICENSE b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/LICENSE deleted file mode 100755 index c4dc63ae..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/LICENSE +++ /dev/null @@ -1,675 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - Just Perfection GNOME Shell Desktop - Copyright (C) 2020-2024 Javad Rahmatzadeh - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Just Perfection GNOME Shell Desktop - Copyright (C) 2020-2024 Javad Rahmatzadeh - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/extension.js deleted file mode 100755 index 83543b4a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/extension.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Extension - * - * @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com> - * @copyright 2020-2024 - * @license GPL-3.0-only - */ - -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Meta from 'gi://Meta'; -import St from 'gi://St'; - -import * as AltTab from 'resource:///org/gnome/shell/ui/altTab.js'; -import * as BackgroundMenu from 'resource:///org/gnome/shell/ui/backgroundMenu.js'; -import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; -import * as OSDWindow from 'resource:///org/gnome/shell/ui/osdWindow.js'; -import * as OverviewControls from 'resource:///org/gnome/shell/ui/overviewControls.js'; -import * as Panel from 'resource:///org/gnome/shell/ui/panel.js'; -import * as SearchController from 'resource:///org/gnome/shell/ui/searchController.js'; -import * as SwitcherPopup from 'resource:///org/gnome/shell/ui/switcherPopup.js'; -import * as WindowMenu from 'resource:///org/gnome/shell/ui/windowMenu.js'; -import * as WindowPreview from 'resource:///org/gnome/shell/ui/windowPreview.js'; -import * as Workspace from 'resource:///org/gnome/shell/ui/workspace.js'; -import * as WorkspacesView from 'resource:///org/gnome/shell/ui/workspacesView.js'; -import * as WorkspaceSwitcherPopup from 'resource:///org/gnome/shell/ui/workspaceSwitcherPopup.js'; -import * as WorkspaceThumbnail from 'resource:///org/gnome/shell/ui/workspaceThumbnail.js'; - -import * as Config from 'resource:///org/gnome/shell/misc/config.js'; -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; - -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import {API} from './lib/API.js'; -import {Manager} from './lib/Manager.js'; - -/** - * Extension entry point - */ -export default class JustPerfection extends Extension -{ - /** - * Instance of API - * - * @type {API|null} - */ - #api = null; - - /** - * Instance of Manager - * - * @type {Manager|null} - */ - #manager = null; - - /** - * Enable extension - * - * @returns {void} - */ - enable() - { - const shellVersion = parseFloat(Config.PACKAGE_VERSION); - - let InterfaceSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.interface'}); - - this.#api = new API( - { - Main, - BackgroundMenu, - OverviewControls, - WorkspaceSwitcherPopup, - SwitcherPopup, - InterfaceSettings, - SearchController, - WorkspaceThumbnail, - WorkspacesView, - Panel, - WindowPreview, - Workspace, - LookingGlass, - MessageTray, - OSDWindow, - WindowMenu, - AltTab, - St, - GLib, - Clutter, - Util, - Meta, - GObject, - }, - shellVersion - ); - - this.#api.open(); - - let settings = this.getSettings(); - - this.#manager = new Manager( - { - API: this.#api, - Settings: settings, - }, - shellVersion - ); - - this.#manager.registerSettingsSignals(); - this.#manager.applyAll(); - } - - /** - * Disable extension - * - * @returns {void} - */ - disable() - { - this.#manager?.revertAll(); - this.#manager = null; - - this.#api?.close(); - this.#api = null; - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/API.js b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/API.js deleted file mode 100755 index b9de6d6a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/API.js +++ /dev/null @@ -1,3113 +0,0 @@ -/** - * API Library - * - * @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com> - * @copyright 2020-2024 - * @license GPL-3.0-only - */ - -const XY_POSITION = { - TOP_START: 0, - TOP_CENTER: 1, - TOP_END: 2, - BOTTOM_START: 3, - BOTTOM_CENTER: 4, - BOTTOM_END: 5, - CENTER_START: 6, - CENTER_CENTER: 7, - CENTER_END: 8, -}; - -const PANEL_POSITION = { - TOP: 0, - BOTTOM: 1, -}; - -const PANEL_BOX_POSITION = { - CENTER: 0, - RIGHT: 1, - LEFT: 2, -}; - -const PANEL_HIDE_MODE = { - ALL: 0, - DESKTOP: 1, -}; - -const SHELL_STATUS = { - NONE: 0, - OVERVIEW: 1, -}; - -const DASH_ICON_SIZES = [16, 22, 24, 32, 40, 48, 56, 64]; - -/** - * API to avoid calling GNOME Shell directly - * and make all parts compatible with different GNOME Shell versions - */ -export class API -{ - /** - * Current shell version - * - * @type {number|null} - */ - #shellVersion = null; - - /** - * Originals holder - * - * @type {object} - */ - #originals = {}; - - /** - * Timeout ids - * - * @type {object} - */ - #timeoutIds = {}; - - /** - * Class Constructor - * - * @param {Object} dependencies - * 'Main' reference to ui::main - * 'BackgroundMenu' reference to ui::backgroundMenu - * 'OverviewControls' reference to ui::overviewControls - * 'WorkspaceSwitcherPopup' reference to ui::workspaceSwitcherPopup - * 'SwitcherPopup' reference to ui::switcherPopup - * 'InterfaceSettings' reference to Gio::Settings for 'org.gnome.desktop.interface' - * 'SearchController' reference to ui::searchController - * 'WorkspaceThumbnail' reference to ui::workspaceThumbnail - * 'WorkspacesView' reference to ui::workspacesView - * 'Panel' reference to ui::panel - * 'WindowPreview' reference to ui::windowPreview - * 'Workspace' reference to ui::workspace - * 'LookingGlass' reference to ui::lookingGlass - * 'MessageTray' reference to ui::messageTray - * 'OSDWindow' reference to ui::osdTray - * 'WindowMenu' reference to ui::windowMenu - * 'AltTab' reference to ui::altTab - * 'St' reference to St - * 'GLib' reference to GLib - * 'Clutter' reference to Clutter - * 'Util' reference to misc::util - * 'Meta' reference to Meta - * 'GObject' reference to GObject - * @param {number} shellVersion float in major.minor format - */ - constructor(dependencies, shellVersion) - { - this._main = dependencies['Main'] || null; - this._backgroundMenu = dependencies['BackgroundMenu'] || null; - this._overviewControls = dependencies['OverviewControls'] || null; - this._workspaceSwitcherPopup = dependencies['WorkspaceSwitcherPopup'] || null; - this._switcherPopup = dependencies['SwitcherPopup'] || null; - this._interfaceSettings = dependencies['InterfaceSettings'] || null; - this._searchController = dependencies['SearchController'] || null; - this._workspaceThumbnail = dependencies['WorkspaceThumbnail'] || null; - this._workspacesView = dependencies['WorkspacesView'] || null; - this._panel = dependencies['Panel'] || null; - this._windowPreview = dependencies['WindowPreview'] || null; - this._workspace = dependencies['Workspace'] || null; - this._lookingGlass = dependencies['LookingGlass'] || null; - this._messageTray = dependencies['MessageTray'] || null; - this._osdWindow = dependencies['OSDWindow'] || null; - this._windowMenu = dependencies['WindowMenu'] || null; - this._altTab = dependencies['AltTab'] || null; - this._st = dependencies['St'] || null; - this._glib = dependencies['GLib'] || null; - this._clutter = dependencies['Clutter'] || null; - this._util = dependencies['Util'] || null; - this._meta = dependencies['Meta'] || null; - this._gobject = dependencies['GObject'] || null; - - this.#shellVersion = shellVersion; - - /** - * whether search entry is visible - * - * @member {boolean} - */ - this._searchEntryVisibility = true; - } - - /** - * prepare everything needed for API - * - * @returns {void} - */ - open() - { - this.UIStyleClassAdd(this.#getAPIClassname('shell-version')); - } - - /** - * remove everything from GNOME Shell been added by this class - * - * @returns {void} - */ - close() - { - this.UIStyleClassRemove(this.#getAPIClassname('shell-version')); - this.#startSearchSignal(false); - this.#computeWorkspacesBoxForStateSetDefault(); - this.#altTabSizesSetDefault(); - - for (let [name, id] of Object.entries(this.#timeoutIds)) { - this._glib.source_remove(id); - delete(this.#timeoutIds[name]); - } - } - - /** - * get x and y align for position - * - * @param int pos position - * see XY_POSITION - * - * @returns {array} - * - 0 Clutter.ActorAlign - * - 1 Clutter.ActorAlign - */ - #xyAlignGet(pos) - { - if (XY_POSITION.TOP_START === pos) { - return [this._clutter.ActorAlign.START, this._clutter.ActorAlign.START]; - } - - if (XY_POSITION.TOP_CENTER === pos) { - return [this._clutter.ActorAlign.CENTER, this._clutter.ActorAlign.START]; - } - - if (XY_POSITION.TOP_END === pos) { - return [this._clutter.ActorAlign.END, this._clutter.ActorAlign.START]; - } - - if (XY_POSITION.CENTER_START === pos) { - return [this._clutter.ActorAlign.START, this._clutter.ActorAlign.CENTER]; - } - - if (XY_POSITION.CENTER_CENTER === pos) { - return [this._clutter.ActorAlign.CENTER, this._clutter.ActorAlign.CENTER]; - } - - if (XY_POSITION.CENTER_END === pos) { - return [this._clutter.ActorAlign.END, this._clutter.ActorAlign.CENTER]; - } - - if (XY_POSITION.BOTTOM_START === pos) { - return [this._clutter.ActorAlign.START, this._clutter.ActorAlign.END]; - } - - if (XY_POSITION.BOTTOM_CENTER === pos) { - return [this._clutter.ActorAlign.CENTER, this._clutter.ActorAlign.END]; - } - - if (XY_POSITION.BOTTOM_END === pos) { - return [this._clutter.ActorAlign.END, this._clutter.ActorAlign.END]; - } - } - - /** - * add to animation duration - * - * @param {number} duration in milliseconds - * - * @returns {number} - */ - #addToAnimationDuration(duration) - { - let settings = this._st.Settings.get(); - - return (settings.enable_animations) ? settings.slow_down_factor * duration : 1; - } - - /** - * get signal id of the event - * - * @param {Gtk.Widget} widget to find signal in - * @param {string} signalName signal name - * - * @returns {number} - */ - #getSignalId(widget, signalName) - { - return this._gobject.signal_handler_find(widget, {signalId: signalName}); - } - - /** - * get the css class name for API - * - * @param {string} type - * - * @returns {string} - */ - #getAPIClassname(type) - { - let starter = 'just-perfection-api-'; - - if (type === 'shell-version') { - let shellVerMajor = Math.trunc(this.#shellVersion); - return `${starter}gnome${shellVerMajor}`; - } - - return `${starter}${type}`; - } - - /** - * set panel size to default - * - * @returns {void} - */ - panelSetDefaultSize() - { - if (!this.#originals['panelHeight']) { - return; - } - - this.panelSetSize(this.#originals['panelHeight'], false); - } - - /** - * change panel size - * - * @param {number} size 0 to 100 - * @param {boolean} fake true means it shouldn't change the last size, - * false otherwise - * - * @returns {void} - */ - panelSetSize(size, fake) - { - if (!this.#originals['panelHeight']) { - this.#originals['panelHeight'] = this._main.panel.height; - } - - if (size > 100 || size < 0) { - return; - } - - this._main.panel.height = size; - - if (!fake) { - this._panelSize = size; - } - } - - /** - * get the last size of the panel - * - * @returns {number} - */ - panelGetSize() - { - if (this._panelSize !== undefined) { - return this._panelSize; - } - - if (this.#originals['panelHeight']) { - return this.#originals['panelHeight']; - } - - return this._main.panel.height; - } - - /** - * emit refresh styles - * this is useful when changed style doesn't emit change because doesn't have - * standard styles. for example, style with only `-natural-hpadding` - * won't notify any change. so you need to call this function - * to refresh that - * - * @returns {void} - */ - #emitRefreshStyles() - { - let classname = this.#getAPIClassname('refresh-styles'); - - this.UIStyleClassAdd(classname); - this.UIStyleClassRemove(classname); - } - - /** - * show panel - * - * @returns {void} - */ - panelShow() - { - this._panelVisibility = true; - - let classname = this.#getAPIClassname('no-panel'); - - if (!this.UIStyleClassContain(classname)) { - return; - } - - // The class name should be removed before addChrome the panelBox - // removing after can cause `st_theme_node_lookup_shadow` crash - this.UIStyleClassRemove(classname); - - let overview = this._main.overview; - let searchEntryParent = overview.searchEntry.get_parent(); - let panelBox = this._main.layoutManager.panelBox; - - panelBox.translation_y = 0; - - this._main.layoutManager.overviewGroup.remove_child(panelBox); - this._main.layoutManager.addChrome(panelBox, { - affectsStruts: true, - trackFullscreen: true, - }); - - if (this._hidePanelWorkareasChangedSignal) { - global.display.disconnect(this._hidePanelWorkareasChangedSignal); - delete(this._hidePanelWorkareasChangedSignal); - } - - if (this._hidePanelHeightSignal) { - panelBox.disconnect(this._hidePanelHeightSignal); - delete(this._hidePanelHeightSignal); - } - - searchEntryParent.set_style(`margin-top: 0;`); - - // hide and show can fix windows going under panel - panelBox.hide(); - panelBox.show(); - this.#fixLookingGlassPosition(); - - if (this.#timeoutIds.panelHide) { - this._glib.source_remove(this.#timeoutIds.panelHide); - delete(this.#timeoutIds.panelHide); - } - } - - /** - * hide panel - * - * @param {mode} hide mode see PANEL_HIDE_MODE. defaults to hide all - * @param {boolean} force apply hide even if it is hidden - * - * @returns {void} - */ - panelHide(mode) - { - this._panelVisibility = false; - this._panelHideMode = mode; - - let overview = this._main.overview; - let searchEntryParent = overview.searchEntry.get_parent(); - let panelBox = this._main.layoutManager.panelBox; - let panelHeight = this._main.panel.height; - let panelPosition = this.panelGetPosition(); - let direction = (panelPosition === PANEL_POSITION.BOTTOM) ? 1 : -1; - - if (panelBox.get_parent() === this._main.layoutManager.uiGroup) { - this._main.layoutManager.removeChrome(panelBox); - this._main.layoutManager.overviewGroup.insert_child_at_index(panelBox, 0); - } - - panelBox.translation_y = (mode === PANEL_HIDE_MODE.DESKTOP) ? 0 : panelHeight * direction; - - if (panelPosition === PANEL_POSITION.TOP) { - // when panel is hidden the first element gets too close to the top, - // so we fix it with top margin in search entry - let marginTop = (mode === PANEL_HIDE_MODE.ALL) ? 15 : panelHeight; - searchEntryParent.set_style(`margin-top: ${marginTop}px;`); - } else { - searchEntryParent.set_style(`margin-top: 0;`); - } - - // hide and show can fix windows going under panel - panelBox.hide(); - panelBox.show(); - this.#fixLookingGlassPosition(); - - if (this._hidePanelWorkareasChangedSignal) { - global.display.disconnect(this._hidePanelWorkareasChangedSignal); - delete(this._hidePanelWorkareasChangedSignal); - } - - this._hidePanelWorkareasChangedSignal = global.display.connect( - 'workareas-changed', - () => { - this.panelHide(this._panelHideMode); - } - ); - - if (!this._hidePanelHeightSignal) { - this._hidePanelHeightSignal = panelBox.connect( - 'notify::height', - () => { - this.panelHide(this._panelHideMode); - } - ); - } - - let classname = this.#getAPIClassname('no-panel'); - this.UIStyleClassAdd(classname); - - // update hot corners since we need to make them available - // outside overview - this._main.layoutManager._updateHotCorners(); - - // Maximized windows will have bad maximized gap after unlock in Wayland - // This is a Mutter issue, - // See https://gitlab.gnome.org/GNOME/mutter/-/issues/1627 - // TODO remove after the issue is fixed on Mutter - if (this._meta.is_wayland_compositor()) { - let duration = this.#addToAnimationDuration(180); - this.#timeoutIds.panelHide = this._glib.timeout_add( - this._glib.PRIORITY_IDLE, - duration, - () => { - panelBox.hide(); - panelBox.show(); - return this._glib.SOURCE_REMOVE; - } - ); - } - } - - /** - * check whether panel is visible - * - * @returns {boolean} - */ - isPanelVisible() - { - if (this._panelVisibility === undefined) { - return true; - } - - return this._panelVisibility; - } - - /** - * check whether dash is visible - * - * @returns {boolean} - */ - isDashVisible() - { - return this._dashVisibility === undefined || this._dashVisibility; - } - - /** - * show dash - * - * @returns {void} - */ - dashShow() - { - if (!this._main.overview.dash || this.isDashVisible()) { - return; - } - - this._dashVisibility = true; - - this._main.overview.dash.show(); - - this._main.overview.dash.height = -1; - this._main.overview.dash.setMaxSize(-1, -1); - - this.#updateWindowPreviewOverlap(); - } - - /** - * hide dash - * - * @returns {void} - */ - dashHide() - { - if (!this._main.overview.dash || !this.isDashVisible()) { - return; - } - - this._dashVisibility = false; - - this._main.overview.dash.hide(); - - this._main.overview.dash.height = 0; - - this.#updateWindowPreviewOverlap(); - } - - /** - * update window preview overlap - * - * @returns {void} - */ - #updateWindowPreviewOverlap() - { - let wpp = this._windowPreview.WindowPreview.prototype; - - if (this.isDashVisible() && wpp.overlapHeightsOld) { - wpp.overlapHeights = wpp.overlapHeightsOld; - delete(wpp.overlapHeightsOld); - return; - } - - if (!this.isDashVisible()) { - wpp.overlapHeightsOld = wpp.overlapHeights; - wpp.overlapHeights = function () { - let [top, bottom] = this.overlapHeightsOld(); - return [top + 24, bottom + 24]; - }; - } - } - - /** - * add class name to the UI group - * - * @param {string} classname class name - * - * @returns {void} - */ - UIStyleClassAdd(classname) - { - this._main.layoutManager.uiGroup.add_style_class_name(classname); - } - - /** - * remove class name from UI group - * - * @param {string} classname class name - * - * @returns {void} - */ - UIStyleClassRemove(classname) - { - this._main.layoutManager.uiGroup.remove_style_class_name(classname); - } - - /** - * check whether UI group has class name - * - * @param {string} classname class name - * - * @returns {boolean} - */ - UIStyleClassContain(classname) - { - return this._main.layoutManager.uiGroup.has_style_class_name(classname); - } - - /** - * enable background menu - * - * @returns {void} - */ - backgroundMenuEnable() - { - if (!this.#originals['backgroundMenuOpen']) { - return; - } - - this._backgroundMenu.BackgroundMenu.prototype.open = this.#originals['backgroundMenuOpen']; - } - - /** - * disable background menu - * - * @returns {void} - */ - backgroundMenuDisable() - { - let backgroundMenuProto = this._backgroundMenu.BackgroundMenu.prototype; - - if (!this.#originals['backgroundMenuOpen']) { - this.#originals['backgroundMenuOpen'] = backgroundMenuProto.open; - } - - backgroundMenuProto.open = () => {}; - } - - /** - * show search - * - * @param {boolean} fake true means it just needs to do the job but - * don't need to change the search visibility status - * - * @returns {void} - */ - searchEntryShow(fake) - { - let classname = this.#getAPIClassname('no-search'); - - if (!this.UIStyleClassContain(classname)) { - return; - } - - this.UIStyleClassRemove(classname); - - let searchEntry = this._main.overview.searchEntry; - let searchEntryParent = searchEntry.get_parent(); - - searchEntryParent.ease({ - height: searchEntry.height, - opacity: 255, - mode: this._clutter.AnimationMode.EASE, - duration: 110, - onComplete: () => { - searchEntryParent.height = -1; - searchEntry.ease({ - opacity: 255, - mode: this._clutter.AnimationMode.EASE, - duration: 700, - }); - }, - }); - - if (!fake) { - this._searchEntryVisibility = true; - } - - this.#computeWorkspacesBoxForStateChanged(); - } - - /** - * hide search - * - * @param {boolean} fake true means it just needs to do the job - * but don't need to change the search visibility status - * - * @returns {void} - */ - searchEntryHide(fake) - { - this.UIStyleClassAdd(this.#getAPIClassname('no-search')); - - let searchEntry = this._main.overview.searchEntry; - let searchEntryParent = searchEntry.get_parent(); - - searchEntry.ease({ - opacity: 0, - mode: this._clutter.AnimationMode.EASE, - duration: 50, - }); - - searchEntryParent.ease({ - height: 0, - opacity: 0, - mode: this._clutter.AnimationMode.EASE, - duration: 120, - }); - - if (!fake) { - this._searchEntryVisibility = false; - } - - this.#computeWorkspacesBoxForStateChanged(); - } - - /** - * enable start search - * - * @returns {void} - */ - startSearchEnable() - { - this.#startSearchSignal(true); - - if (!this.#originals['startSearch']) { - return; - } - - this._searchController.SearchController.prototype.startSearch = this.#originals['startSearch']; - } - - /** - * disable start search - * - * @returns {void} - */ - startSearchDisable() - { - this.#startSearchSignal(false); - - if (!this.#originals['startSearch']) { - this.#originals['startSearch'] = this._searchController.SearchController.prototype.startSearch - } - - this._searchController.SearchController.prototype.startSearch = () => {}; - } - - /** - * add search signals that needs to be show search entry when the - * search entry is hidden - * - * @param {boolean} add true means add the signal, false means remove - * the signal - * - * @returns {void} - */ - #startSearchSignal(add) - { - let controller - = this._main.overview.viewSelector || - this._main.overview._overview.viewSelector || - this._main.overview._overview.controls._searchController; - - // remove - if (!add) { - if (this._searchActiveSignal) { - controller.disconnect(this._searchActiveSignal); - this._searchActiveSignal = null; - } - return; - } - - // add - if (this._searchActiveSignal) { - return; - } - - this._searchActiveSignal = controller.connect('notify::search-active', () => { - if (this._searchEntryVisibility) { - return; - } - - let inSearch = controller.searchActive; - - if (inSearch) { - this.UIStyleClassAdd(this.#getAPIClassname('type-to-search')); - this.searchEntryShow(true); - } else { - this.UIStyleClassRemove(this.#getAPIClassname('type-to-search')); - this.searchEntryHide(true); - } - }); - } - - /** - * enable OSD - * - * @returns {void} - */ - OSDEnable() - { - if (!this.#originals['osdWindowManagerShow']) { - return; - } - - this._main.osdWindowManager.show = this.#originals['osdWindowManagerShow']; - } - - /** - * disable OSD - * - * @returns {void} - */ - OSDDisable() - { - if (!this.#originals['osdWindowManagerShow']) { - this.#originals['osdWindowManagerShow'] - = this._main.osdWindowManager.show; - } - - this._main.osdWindowManager.show = () => {}; - } - - /** - * enable workspace popup - * - * @returns {void} - */ - workspacePopupEnable() - { - if (!this.#originals['workspaceSwitcherPopupDisplay']) { - return; - } - - this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype.display - = this.#originals['workspaceSwitcherPopupDisplay'] - } - - /** - * disable workspace popup - * - * @returns {void} - */ - workspacePopupDisable() - { - if (!this.#originals['workspaceSwitcherPopupDisplay']) { - this.#originals['workspaceSwitcherPopupDisplay'] - = this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype.display; - } - - this._workspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype.display = (index) => { - return false; - }; - } - - /** - * show workspace switcher - * - * @returns {void} - */ - workspaceSwitcherShow() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-workspace')); - - this.#workspaceSwitcherShouldShowSetToLast(); - } - - /** - * hide workspace switcher - * - * @returns {void} - */ - workspaceSwitcherHide() - { - this.workspaceSwitcherShouldShow(false, true); - - // should be after `this.workspaceSwitcherShouldShow()` - // since it checks whether it's visible or not - this.UIStyleClassAdd(this.#getAPIClassname('no-workspace')); - } - - /** - * check whether workspace switcher is visible - * - * @returns {boolean} - */ - isWorkspaceSwitcherVisible() - { - return !this.UIStyleClassContain(this.#getAPIClassname('no-workspace')); - } - - /** - * set workspace switcher to its default size - * - * @returns {void} - */ - workspaceSwitcherSetDefaultSize() - { - let thumbnailsBox = this._main.overview._overview._controls._thumbnailsBox; - let ThumbnailsBoxProto = this._workspaceThumbnail.ThumbnailsBox.prototype; - - if (!ThumbnailsBoxProto._initOld) { - return; - } - - ThumbnailsBoxProto._init = ThumbnailsBoxProto._initOld; - delete(ThumbnailsBoxProto._initOld); - - thumbnailsBox._maxThumbnailScale = this._workspaceThumbnail.MAX_THUMBNAIL_SCALE; - } - - /** - * set workspace switcher size - * - * @param {number} size in float - * - * @returns {void} - */ - workspaceSwitcherSetSize(size) - { - let thumbnailsBox = this._main.overview._overview._controls._thumbnailsBox; - let ThumbnailsBoxProto = this._workspaceThumbnail.ThumbnailsBox.prototype; - - thumbnailsBox._maxThumbnailScale = size; - - if (!ThumbnailsBoxProto._initOld) { - ThumbnailsBoxProto._initOld = ThumbnailsBoxProto._init; - } - - ThumbnailsBoxProto._init = function(...params) { - this._maxThumbnailScale = size; - this._initOld(...params); - }; - } - - /** - * add element to stage - * - * @param {St.Widget} element widget - * - * @returns {void} - */ - chromeAdd(element) - { - this._main.layoutManager.addChrome(element, { - affectsInputRegion : true, - affectsStruts : false, - trackFullscreen : true, - }); - } - - /** - * remove element from stage - * - * @param {St.Widget} element widget - * - * @returns {void} - */ - chromeRemove(element) - { - this._main.layoutManager.removeChrome(element); - } - - /** - * show activities button - * - * @returns {void} - */ - activitiesButtonShow() - { - let activities = this._main.panel.statusArea.activities; - - if (!this.isLocked() && activities) { - activities.container.show(); - } - } - - /** - * hide activities button - * - * @returns {void} - */ - activitiesButtonHide() - { - let activities = this._main.panel.statusArea.activities; - - if (activities) { - activities.container.hide(); - } - } - - /** - * show date menu - * - * @returns {void} - */ - dateMenuShow() - { - if (!this.isLocked()) { - this._main.panel.statusArea.dateMenu.container.show(); - } - } - - /** - * hide date menu - * - * @returns {void} - */ - dateMenuHide() - { - this._main.panel.statusArea.dateMenu.container.hide(); - } - - /** - * show keyboard layout - * - * @returns {void} - */ - keyboardLayoutShow() - { - this._main.panel.statusArea.keyboard.container.show(); - } - - /** - * hide keyboard layout - * - * @returns {void} - */ - keyboardLayoutHide() - { - this._main.panel.statusArea.keyboard.container.hide(); - } - - /** - * show accessibility menu - * - * @returns {void} - */ - accessibilityMenuShow() - { - this._main.panel.statusArea.a11y?.container.show(); - } - - /** - * hide accessibility menu - * - * @returns {void} - */ - accessibilityMenuHide() - { - this._main.panel.statusArea.a11y?.container.hide(); - } - - /** - * show quick settings menu - * - * @returns {void} - */ - quickSettingsMenuShow() - { - if (this.#shellVersion < 43) { - return; - } - - this._main.panel.statusArea.quickSettings.container.show(); - } - - /** - * hide quick settings menu - * - * @returns {void} - */ - quickSettingsMenuHide() - { - if (this.#shellVersion < 43) { - return; - } - - this._main.panel.statusArea.quickSettings.container.hide(); - } - - /** - * check whether lock dialog is currently showing - * - * @returns {boolean} - */ - isLocked() - { - return this._main.sessionMode.isLocked; - } - - /** - * enable window picker icon - * - * @returns {void} - */ - windowPickerIconEnable() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-window-picker-icon')); - } - - /** - * disable window picker icon - * - * @returns {void} - */ - windowPickerIconDisable() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-window-picker-icon')); - } - - /** - * show power icon - * - * @returns {void} - */ - powerIconShow() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-power-icon')); - } - - /** - * hide power icon - * - * @returns {void} - */ - powerIconHide() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-power-icon')); - } - - /** - * get primary monitor information - * - * @returns {false|Object} false when monitor does not exist | object - * x: int - * y: int - * width: int - * height: int - * geometryScale: float - */ - monitorGetInfo() - { - let pMonitor = this._main.layoutManager.primaryMonitor; - - if (!pMonitor) { - return false; - } - - return { - 'x': pMonitor.x, - 'y': pMonitor.y, - 'width': pMonitor.width, - 'height': pMonitor.height, - 'geometryScale': pMonitor.geometry_scale, - }; - } - - /** - * get panel position - * - * @returns {number} see PANEL_POSITION - */ - panelGetPosition() - { - if (this._panelPosition === undefined) { - return PANEL_POSITION.TOP; - } - - return this._panelPosition; - } - - /** - * move panel position - * - * @param {number} position see PANEL_POSITION - * @param {boolean} force allow to set even when the current position - * is the same - * - * @returns {void} - */ - panelSetPosition(position, force = false) - { - let monitorInfo = this.monitorGetInfo(); - let panelBox = this._main.layoutManager.panelBox; - - if (!force && position === this.panelGetPosition()) { - return; - } - - if (position === PANEL_POSITION.TOP) { - this._panelPosition = PANEL_POSITION.TOP; - if (this._workareasChangedSignal) { - global.display.disconnect(this._workareasChangedSignal); - this._workareasChangedSignal = null; - } - if (this._panelHeightSignal) { - panelBox.disconnect(this._panelHeightSignal); - this._panelHeightSignal = null; - } - let topX = (monitorInfo) ? monitorInfo.x : 0; - let topY = (monitorInfo) ? monitorInfo.y : 0; - panelBox.set_position(topX, topY); - this.UIStyleClassRemove(this.#getAPIClassname('bottom-panel')); - this.#fixLookingGlassPosition(); - return; - } - - this._panelPosition = PANEL_POSITION.BOTTOM; - - // only change it when a monitor detected - // 'workareas-changed' signal will do the job on next monitor detection - if (monitorInfo) { - let BottomX = monitorInfo.x; - let BottomY = monitorInfo.y + monitorInfo.height - this.panelGetSize(); - - panelBox.set_position(BottomX, BottomY); - this.UIStyleClassAdd(this.#getAPIClassname('bottom-panel')); - } - - if (!this._workareasChangedSignal) { - this._workareasChangedSignal - = global.display.connect('workareas-changed', () => { - this.panelSetPosition(PANEL_POSITION.BOTTOM, true); - }); - } - - if (!this._panelHeightSignal) { - this._panelHeightSignal = panelBox.connect('notify::height', () => { - this.panelSetPosition(PANEL_POSITION.BOTTOM, true); - }); - } - - this.#fixLookingGlassPosition(); - } - - /** - * fix looking glass position - * - * @returns {void} - */ - #fixLookingGlassPosition() - { - let lookingGlassProto = this._lookingGlass.LookingGlass.prototype; - - if (this.#originals['lookingGlassResize'] === undefined) { - this.#originals['lookingGlassResize'] = lookingGlassProto._resize; - } - - if (this.panelGetPosition() === PANEL_POSITION.TOP && this.isPanelVisible()) { - - lookingGlassProto._resize = this.#originals['lookingGlassResize']; - delete(lookingGlassProto._oldResizeMethod); - delete(this.#originals['lookingGlassResize']); - - return; - } - - if (lookingGlassProto._oldResizeMethod === undefined) { - lookingGlassProto._oldResizeMethod = this.#originals['lookingGlassResize']; - - const Main = this._main; - - lookingGlassProto._resize = function () { - let panelHeight = Main.layoutManager.panelBox.height; - this._oldResizeMethod(); - this._targetY -= panelHeight; - this._hiddenY -= panelHeight; - }; - } - } - - /** - * enable panel notification icon - * - * @returns {void} - */ - panelNotificationIconEnable() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-panel-notification-icon')); - } - - /** - * disable panel notification icon - * - * @returns {void} - */ - panelNotificationIconDisable() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-panel-notification-icon')); - } - - /** - * disconnect all clock menu position signals - * - * @returns {void} - */ - #disconnectClockMenuPositionSignals() - { - let panelBoxes = [ - this._main.panel._centerBox, - this._main.panel._rightBox, - this._main.panel._leftBox, - ]; - - if (this._clockMenuPositionSignals) { - for (let i = 0; i <= 2; i++) { - panelBoxes[i].disconnect(this._clockMenuPositionSignals[i]); - } - delete(this._clockMenuPositionSignals); - } - } - - /** - * set the clock menu position to default - * - * @returns {void} - */ - clockMenuPositionSetDefault() - { - this.clockMenuPositionSet(0, 0); - this.#disconnectClockMenuPositionSignals(); - } - - /** - * set the clock menu position - * - * @param {number} pos see PANEL_BOX_POSITION - * @param {number} offset starts from 0 - * - * @returns {void} - */ - clockMenuPositionSet(pos, offset) - { - let dateMenu = this._main.panel.statusArea.dateMenu; - - let panelBoxes = [ - this._main.panel._centerBox, - this._main.panel._rightBox, - this._main.panel._leftBox, - ]; - - this.#disconnectClockMenuPositionSignals(); - - let fromPos = -1; - let fromIndex = -1; - let toIndex = -1; - let childLength = 0; - for (let i = 0; i <= 2; i++) { - let child = panelBoxes[i].get_children(); - let childIndex = child.indexOf(dateMenu.container); - if (childIndex !== -1) { - fromPos = i; - fromIndex = childIndex; - childLength = panelBoxes[pos].get_children().length; - toIndex = (offset > childLength) ? childLength : offset; - break; - } - } - - // couldn't find the from and to position because it has been removed - if (fromPos === -1 || fromIndex === -1 || toIndex === -1) { - return; - } - - if (pos === fromPos && toIndex === fromIndex) { - return; - } - - panelBoxes[fromPos].remove_child(dateMenu.container); - panelBoxes[pos].insert_child_at_index(dateMenu.container, toIndex); - - if (this.isLocked()) { - this.dateMenuHide(); - } - - if (!this._clockMenuPositionSignals) { - this._clockMenuPositionSignals = [null, null, null]; - for (let i = 0; i <= 2; i++) { - this._clockMenuPositionSignals[i] = panelBoxes[i].connect( - (this.#shellVersion >= 46) ? 'child-added' : 'actor-added', - () => { - this.clockMenuPositionSet(pos, offset); - } - ); - } - } - } - - /** - * enable show apps button - * - * @returns {void} - */ - showAppsButtonEnable() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-show-apps-button')); - } - - /** - * disable show apps button - * - * @returns {void} - */ - showAppsButtonDisable() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-show-apps-button')); - } - - /** - * set animation speed as default - * - * @returns {void} - */ - animationSpeedSetDefault() - { - if (this.#originals['StSlowDownFactor'] === undefined) { - return; - } - - this._st.Settings.get().slow_down_factor = this.#originals['StSlowDownFactor']; - } - - /** - * change animation speed - * - * @param {number} factor in float. bigger number means slower - * - * @returns {void} - */ - animationSpeedSet(factor) - { - if (this.#originals['StSlowDownFactor'] === undefined) { - this.#originals['StSlowDownFactor'] - = this._st.Settings.get().slow_down_factor; - } - - this._st.Settings.get().slow_down_factor = factor; - } - - /** - * set the enable animation as default - * - * @returns {void} - */ - enableAnimationsSetDefault() - { - if (this.#originals['enableAnimations'] === undefined) { - return; - } - - let status = this.#originals['enableAnimations']; - - this._interfaceSettings.set_boolean('enable-animations', status); - } - - /** - * set the enable animation status - * - * @param {boolean} status true to enable, false otherwise - * - * @returns {void} - */ - enableAnimationsSet(status) - { - if (this.#originals['enableAnimations'] === undefined) { - this.#originals['enableAnimations'] - = this._interfaceSettings.get_boolean('enable-animations'); - } - - this._interfaceSettings.set_boolean('enable-animations', status); - } - - /** - * enable focus when window demands attention happens - * - * @returns {void} - */ - windowDemandsAttentionFocusEnable() - { - if ( - this._displayWindowDemandsAttentionSignal || - this._displayWindowMarkedUrgentSignal - ) { - return; - } - - let display = global.display; - - let demandFunction = (display, window) => { - if (!window || window.has_focus() || window.is_skip_taskbar()) { - return; - } - this._main.activateWindow(window); - }; - - this._displayWindowDemandsAttentionSignal - = display.connect('window-demands-attention', demandFunction); - this._displayWindowMarkedUrgentSignal - = display.connect('window-marked-urgent', demandFunction); - - // since removing '_windowDemandsAttentionId' doesn't have any effect - // we remove the original signal and re-connect it on disable - let signalId = this.#getSignalId(global.display, 'window-demands-attention'); - let signalId2 = this.#getSignalId(global.display, 'window-marked-urgent'); - display.disconnect(signalId); - display.disconnect(signalId2); - } - - /** - * disable focus when window demands attention happens - * - * @returns {void} - */ - windowDemandsAttentionFocusDisable() - { - if ( - !this._displayWindowDemandsAttentionSignal || - !this._displayWindowMarkedUrgentSignal - ) { - return; - } - - let display = global.display; - - display.disconnect(this._displayWindowDemandsAttentionSignal); - display.disconnect(this._displayWindowMarkedUrgentSignal); - this._displayWindowDemandsAttentionSignal = null; - this._displayWindowMarkedUrgentSignal = null; - - let wah = this._main.windowAttentionHandler; - wah._windowDemandsAttentionId = display.connect( - 'window-demands-attention', - wah._onWindowDemandsAttention.bind(wah) - ); - wah._windowDemandsAttentionId = display.connect( - 'window-marked-urgent', - wah._onWindowDemandsAttention.bind(wah) - ); - } - - /** - * enable maximizing windows on creation - * - * @returns {void} - */ - windowMaximizedOnCreateEnable() - { - if (this._displayWindowCreatedSignal) { - return; - } - - let display = global.display; - - let createdFunction = (display, window) => { - if (window.can_maximize()) { - window.maximize(this._meta.MaximizeFlags.HORIZONTAL | this._meta.MaximizeFlags.VERTICAL); - } - }; - - this._displayWindowCreatedSignal = display.connect('window-created', createdFunction); - } - - /** - * disable maximizing windows on creation - * - * @returns {void} - */ - windowMaximizedOnCreateDisable() - { - if (!this._displayWindowCreatedSignal) { - return; - } - - let display = global.display; - - display.disconnect(this._displayWindowCreatedSignal); - delete(this._displayWindowCreatedSignal); - } - - /** - * set startup status - * - * @param {number} status see SHELL_STATUS for available status - * - * @returns {void} - */ - startupStatusSet(status) - { - let sessionMode = this._main.sessionMode; - let layoutManager = this._main.layoutManager; - - if (!layoutManager._startingUp) { - return; - } - - if (this.#originals['sessionModeHasOverview'] === undefined) { - this.#originals['sessionModeHasOverview'] = sessionMode.hasOverview; - } - - let ControlsState = this._overviewControls.ControlsState; - let Controls = this._main.overview._overview.controls; - - switch (status) { - - case SHELL_STATUS.NONE: - sessionMode.hasOverview = false; - layoutManager.startInOverview = false; - Controls._stateAdjustment.value = ControlsState.HIDDEN; - break; - - case SHELL_STATUS.OVERVIEW: - default: - sessionMode.hasOverview = true; - layoutManager.startInOverview = true; - break; - } - - if (!this._startupCompleteSignal) { - this._startupCompleteSignal - = layoutManager.connect('startup-complete', () => { - sessionMode.hasOverview = this.#originals['sessionModeHasOverview']; - }); - } - } - - /** - * set startup status to default - * - * @returns {void} - */ - startupStatusSetDefault() - { - if (this.#originals['sessionModeHasOverview'] === undefined) { - return; - } - - if (this._startupCompleteSignal) { - this._main.layoutManager.disconnect(this._startupCompleteSignal); - } - } - - /** - * set dash icon size to default - * - * @returns {void} - */ - dashIconSizeSetDefault() - { - let classnameStarter = this.#getAPIClassname('dash-icon-size'); - - DASH_ICON_SIZES.forEach(size => { - this.UIStyleClassRemove(classnameStarter + size); - }); - } - - /** - * set dash icon size - * - * @param {number} size in pixels - * see DASH_ICON_SIZES for available sizes - * - * @returns {void} - */ - dashIconSizeSet(size) - { - this.dashIconSizeSetDefault(); - - if (!DASH_ICON_SIZES.includes(size)) { - return; - } - - let classnameStarter = this.#getAPIClassname('dash-icon-size'); - - this.UIStyleClassAdd(classnameStarter + size); - } - - /** - * change ControlsManagerLayout._computeWorkspacesBoxForState - * base on the current state - * - * @returns {void} - */ - #computeWorkspacesBoxForStateChanged() - { - let controlsLayout = this._main.overview._overview._controls.layout_manager; - - if (!this.#originals['computeWorkspacesBoxForState']) { - this.#originals['computeWorkspacesBoxForState'] - = controlsLayout._computeWorkspacesBoxForState; - } - - controlsLayout._computeWorkspacesBoxForState = (state, box, searchHeight, ...args) => { - - let inAppGrid = state === this._overviewControls.ControlsState.APP_GRID; - - if (inAppGrid && !this._searchEntryVisibility) { - // We need some spacing on top of workspace box in app grid - // when the search entry is not visible. - searchHeight = 40; - } - - box = this.#originals['computeWorkspacesBoxForState'].call( - controlsLayout, state, box, searchHeight, ...args); - - if (inAppGrid && this._workspacesInAppGridHeight !== undefined) { - box.set_size( - box.get_width(), - this._workspacesInAppGridHeight - ); - } - - return box; - }; - - // Since workspace background has shadow around it, it can cause - // unwanted shadows in app grid when the workspace height is 0. - // so we are removing the shadow when we are in app grid - if (!this._appButtonForComputeWorkspacesSignal) { - this._appButtonForComputeWorkspacesSignal = - this._main.overview.dash.showAppsButton.connect( - 'notify::checked', - () => { - let checked = this._main.overview.dash.showAppsButton.checked; - let classname = this.#getAPIClassname('no-workspaces-in-app-grid'); - if (checked) { - this.UIStyleClassAdd(classname); - } else { - this.UIStyleClassRemove(classname); - } - } - ); - } - } - - /** - * change ControlsManagerLayout._computeWorkspacesBoxForState to its default - * - * @returns {void} - */ - #computeWorkspacesBoxForStateSetDefault() - { - if (!this.#originals['computeWorkspacesBoxForState']) { - return; - } - - let controlsLayout = this._main.overview._overview._controls.layout_manager; - - controlsLayout._computeWorkspacesBoxForState - = this.#originals['computeWorkspacesBoxForState']; - - if (this._appButtonForComputeWorkspacesSignal) { - let showAppsButton = this._main.overview.dash.showAppsButton; - showAppsButton.disconnect(this._appButtonForComputeWorkspacesSignal); - delete(this._appButtonForComputeWorkspacesSignal); - this.UIStyleClassRemove(this.#getAPIClassname('no-workspaces-in-app-grid')); - } - } - - /** - * disable workspaces in app grid - * - * @returns {void} - */ - workspacesInAppGridDisable() - { - this._workspacesInAppGridHeight = 0; - this.#computeWorkspacesBoxForStateChanged(); - } - - /** - * enable workspaces in app grid - * - * @returns {void} - */ - workspacesInAppGridEnable() - { - if (this._workspacesInAppGridHeight === undefined) { - return; - } - - delete(this._workspacesInAppGridHeight); - this.#computeWorkspacesBoxForStateChanged(); - } - - /** - * change notification banner position - * - * @param {number} pos - * see XY_POSITION for available positions - * - * @returns {void} - */ - notificationBannerPositionSet(pos) - { - let messageTray = this._main.messageTray; - let bannerBin = messageTray._bannerBin; - - if (this.#originals['bannerAlignmentX'] === undefined) { - this.#originals['bannerAlignmentX'] = messageTray.bannerAlignment; - } - - if (this.#originals['bannerAlignmentY'] === undefined) { - this.#originals['bannerAlignmentY'] = bannerBin.get_y_align(); - } - - if (this.#originals['hideNotification'] === undefined) { - this.#originals['hideNotification'] = messageTray._hideNotification; - } - - // TOP - messageTray._hideNotification = this.#originals['hideNotification']; - - bannerBin.set_y_align(this._clutter.ActorAlign.START); - - if (pos === XY_POSITION.TOP_START) { - messageTray.bannerAlignment = this._clutter.ActorAlign.START; - return; - } - - if (pos === XY_POSITION.TOP_END) { - messageTray.bannerAlignment = this._clutter.ActorAlign.END; - return; - } - - if (pos === XY_POSITION.TOP_CENTER) { - messageTray.bannerAlignment = this._clutter.ActorAlign.CENTER; - return; - } - - // BOTTOM - - // >> - // This block is going to fix the animation when the notification is - // in bottom area - // this is the same function from (ui.messageTray.messageTray._hideNotification) - // with clutter animation mode set to EASE. - // because the EASE_OUT_BACK (original code) causes glitch when - // the tray is on bottom - const State = this._messageTray.State; - const ANIMATION_TIME = this._messageTray.ANIMATION_TIME; - const Clutter = this._clutter; - - messageTray._hideNotification = function (animate) { - this._notificationFocusGrabber.ungrabFocus(); - this._banner.disconnectObject(this); - this._resetNotificationLeftTimeout(); - this._bannerBin.remove_all_transitions(); - - if (animate) { - this._notificationState = State.HIDING; - this._bannerBin.ease({ - opacity: 0, - duration: ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE, - }); - this._bannerBin.ease({ - opacity: 0, - y: this._bannerBin.height, - duration: ANIMATION_TIME, - mode: Clutter.AnimationMode.EASE, - onComplete: () => { - this._notificationState = State.HIDDEN; - this._hideNotificationCompleted(); - this._updateState(); - }, - }); - } else { - this._bannerBin.y = this._bannerBin.height; - this._bannerBin.opacity = 0; - this._notificationState = State.HIDDEN; - this._hideNotificationCompleted(); - } - } - // << - - bannerBin.set_y_align(this._clutter.ActorAlign.END); - - if (pos === XY_POSITION.BOTTOM_START) { - messageTray.bannerAlignment = this._clutter.ActorAlign.START; - return; - } - - if (pos === XY_POSITION.BOTTOM_END) { - messageTray.bannerAlignment = this._clutter.ActorAlign.END; - return; - } - - if (pos === XY_POSITION.BOTTOM_CENTER) { - messageTray.bannerAlignment = this._clutter.ActorAlign.CENTER; - return; - } - } - - /** - * set notification banner position to default position - * - * @returns {void} - */ - notificationBannerPositionSetDefault() - { - if (this.#originals['bannerAlignmentX'] === undefined || - this.#originals['bannerAlignmentY'] === undefined || - this.#originals['hideNotification'] === undefined - ) { - return; - } - - let messageTray = this._main.messageTray; - let bannerBin = messageTray._bannerBin; - - messageTray.bannerAlignment = this.#originals['bannerAlignmentX']; - bannerBin.set_y_align(this.#originals['bannerAlignmentY']); - messageTray._hideNotification = this.#originals['hideNotification']; - } - - /** - * set the workspace switcher to always/never show - * - * @param {boolean} show true for always show, false for never show - * @param {boolean} fake true means set the current should show status - * - * @returns {void} - */ - workspaceSwitcherShouldShow(shouldShow = true, fake = false) - { - if (!fake) { - this._shouldShow = shouldShow; - } - - if (!this.isWorkspaceSwitcherVisible()) { - return; - } - - let ThumbnailsBoxProto = this._workspaceThumbnail.ThumbnailsBox.prototype; - - if (!this.#originals['updateShouldShow']) { - this.#originals['updateShouldShow'] = ThumbnailsBoxProto._updateShouldShow; - } - - ThumbnailsBoxProto._updateShouldShow = function () { - if (this._shouldShow === shouldShow) { - return; - } - this._shouldShow = shouldShow; - this.notify('should-show'); - }; - } - - /** - * set the always show workspace switcher status to last real status - * - * @returns {void} - */ - #workspaceSwitcherShouldShowSetToLast() - { - if (this._shouldShow === undefined) { - this.workspaceSwitcherShouldShowSetDefault(); - return; - } - - this.workspaceSwitcherShouldShow(this._shouldShow); - } - - /** - * set the always show workspace switcher status to default - * - * @returns {void} - */ - workspaceSwitcherShouldShowSetDefault() - { - if (!this.#originals['updateShouldShow'] || !this.isWorkspaceSwitcherVisible()) { - return; - } - - let ThumbnailsBoxProto = this._workspaceThumbnail.ThumbnailsBox.prototype; - ThumbnailsBoxProto._updateShouldShow = this.#originals['updateShouldShow']; - delete(this.#originals['updateShouldShow']); - delete(this._shouldShow); - } - - /** - * set panel button hpadding to default - * - * @returns {void} - */ - panelButtonHpaddingSetDefault() - { - if (this._panelButtonHpaddingSize === undefined) { - return; - } - - let classnameStarter = this.#getAPIClassname('panel-button-padding-size'); - this.UIStyleClassRemove(classnameStarter + this._panelButtonHpaddingSize); - this.#emitRefreshStyles(); - - delete this._panelButtonHpaddingSize; - } - - /** - * set panel button hpadding size - * - * @param {number} size in pixels (0 - 60) - * - * @returns {void} - */ - panelButtonHpaddingSizeSet(size) - { - this.panelButtonHpaddingSetDefault(); - - if (size < 0 || size > 60) { - return; - } - - this._panelButtonHpaddingSize = size; - - let classnameStarter = this.#getAPIClassname('panel-button-padding-size'); - this.UIStyleClassAdd(classnameStarter + size); - this.#emitRefreshStyles(); - } - - /** - * set panel indicator padding to default - * - * @returns {void} - */ - panelIndicatorPaddingSetDefault() - { - if (this._panelIndicatorPaddingSize === undefined) { - return; - } - - let classnameStarter = this.#getAPIClassname('panel-indicator-padding-size'); - this.UIStyleClassRemove(classnameStarter + this._panelIndicatorPaddingSize); - this.#emitRefreshStyles(); - - delete this._panelIndicatorPaddingSize; - } - - /** - * set panel indicator padding size - * - * @param {number} size in pixels (0 - 60) - * - * @returns {void} - */ - panelIndicatorPaddingSizeSet(size) - { - this.panelIndicatorPaddingSetDefault(); - - if (size < 0 || size > 60) { - return; - } - - this._panelIndicatorPaddingSize = size; - - let classnameStarter = this.#getAPIClassname('panel-indicator-padding-size'); - this.UIStyleClassAdd(classnameStarter + size); - this.#emitRefreshStyles(); - } - - /** - * get window preview prototype - * - * @returns {Object} - */ - #windowPreviewGetPrototype() - { - return this._windowPreview.WindowPreview.prototype; - } - - /** - * enable window preview caption - * - * @returns {void} - */ - windowPreviewCaptionEnable() - { - if (!this.#originals['windowPreviewGetCaption']) { - return; - } - - let windowPreviewProto = this.#windowPreviewGetPrototype(); - windowPreviewProto._getCaption = this.#originals['windowPreviewGetCaption']; - - this.UIStyleClassRemove(this.#getAPIClassname('no-window-caption')); - } - - /** - * disable window preview caption - * - * @returns {void} - */ - windowPreviewCaptionDisable() - { - let windowPreviewProto = this.#windowPreviewGetPrototype(); - - if (!this.#originals['windowPreviewGetCaption']) { - this.#originals['windowPreviewGetCaption'] = windowPreviewProto._getCaption; - } - - windowPreviewProto._getCaption = () => { - return ''; - }; - - this.UIStyleClassAdd(this.#getAPIClassname('no-window-caption')); - } - - /** - * set workspace background border radius to default size - * - * @returns {void} - */ - workspaceBackgroundRadiusSetDefault() - { - if (this._workspaceBackgroundRadiusSize === undefined) { - return; - } - - let workspaceBackgroundProto = this._workspace.WorkspaceBackground.prototype; - - workspaceBackgroundProto._updateBorderRadius - = this.#originals['workspaceBackgroundUpdateBorderRadius']; - - let classnameStarter = this.#getAPIClassname('workspace-background-radius-size'); - this.UIStyleClassRemove(classnameStarter + this._workspaceBackgroundRadiusSize); - - delete this._workspaceBackgroundRadiusSize; - } - - /** - * set workspace background border radius size - * - * @param {number} size in pixels (0 - 60) - * - * @returns {void} - */ - workspaceBackgroundRadiusSet(size) - { - if (size < 0 || size > 60) { - return; - } - - this.workspaceBackgroundRadiusSetDefault(); - - let workspaceBackgroundProto = this._workspace.WorkspaceBackground.prototype; - - if (!this.#originals['workspaceBackgroundUpdateBorderRadius']) { - this.#originals['workspaceBackgroundUpdateBorderRadius'] - = workspaceBackgroundProto._updateBorderRadius; - } - - const Util = this._util; - const St = this._st; - - workspaceBackgroundProto._updateBorderRadius = function () { - const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); - const cornerRadius = scaleFactor * size; - - const backgroundContent = this._bgManager.backgroundActor.content; - backgroundContent.rounded_clip_radius = - Util.lerp(0, cornerRadius, this._stateAdjustment.value); - } - - this._workspaceBackgroundRadiusSize = size; - - let classnameStarter = this.#getAPIClassname('workspace-background-radius-size'); - this.UIStyleClassAdd(classnameStarter + size); - } - - /** - * enable workspace wraparound - * - * @returns {void} - */ - workspaceWraparoundEnable() - { - let metaWorkspaceProto = this._meta.Workspace.prototype; - - if (!this.#originals['metaWorkspaceGetNeighbor']) { - this.#originals['metaWorkspaceGetNeighbor'] - = metaWorkspaceProto.get_neighbor; - } - - const Meta = this._meta; - - metaWorkspaceProto.get_neighbor = function (dir) { - - let index = this.index(); - let lastIndex = global.workspace_manager.n_workspaces - 1; - let neighborIndex; - - if (dir === Meta.MotionDirection.UP || dir === Meta.MotionDirection.LEFT) { - // prev - neighborIndex = (index > 0) ? index - 1 : lastIndex; - } else { - // next - neighborIndex = (index < lastIndex) ? index + 1 : 0; - } - - return global.workspace_manager.get_workspace_by_index(neighborIndex); - }; - } - - /** - * disable workspace wraparound - * - * @returns {void} - */ - workspaceWraparoundDisable() - { - if (!this.#originals['metaWorkspaceGetNeighbor']) { - return; - } - - let metaWorkspaceProto = this._meta.Workspace.prototype; - metaWorkspaceProto.get_neighbor = this.#originals['metaWorkspaceGetNeighbor']; - } - - /** - * enable window preview close button - * - * @returns {void} - */ - windowPreviewCloseButtonEnable() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-window-close')); - } - - /** - * disable window preview close button - * - * @returns {void} - */ - windowPreviewCloseButtonDisable() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-window-close')); - } - - /** - * enable ripple box - * - * @returns {void} - */ - rippleBoxEnable() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-ripple-box')); - } - - /** - * disable ripple box - * - * @returns {void} - */ - rippleBoxDisable() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-ripple-box')); - } - - /** - * unblock overlay key - * - * @returns {void} - */ - unblockOverlayKey() - { - if (!this._overlayKeyOldSignalId) { - return; - } - - this._gobject.signal_handler_unblock( - global.display, - this._overlayKeyOldSignalId - ); - - delete(this._overlayKeyOldSignalId); - } - - /** - * block overlay key - * - * @returns {void} - */ - blockOverlayKey() - { - this._overlayKeyOldSignalId = this.#getSignalId(global.display, 'overlay-key'); - - if (!this._overlayKeyOldSignalId) { - return; - } - - this._gobject.signal_handler_block(global.display, this._overlayKeyOldSignalId); - } - - /** - * enable double super press to toggle app grid - * - * @returns {void} - */ - doubleSuperToAppGridEnable() - { - if (this._isDoubleSuperToAppGrid === true) { - return; - } - - if (!this._overlayKeyNewSignalId) { - return; - } - - global.display.disconnect(this._overlayKeyNewSignalId); - delete(this._overlayKeyNewSignalId); - this.unblockOverlayKey(); - - this._isDoubleSuperToAppGrid = true; - } - - /** - * disable double super press to toggle app grid - * - * @returns {void} - */ - doubleSuperToAppGridDisable() - { - if (this._isDoubleSuperToAppGrid === false) { - return; - } - - this.blockOverlayKey(); - - this._overlayKeyNewSignalId = global.display.connect('overlay-key', () => { - this._main.overview.toggle(); - }); - - this._isDoubleSuperToAppGrid = false; - } - - /** - * disable the removal of switcher popup delay - * - * @returns {void} - */ - switcherPopupDelaySetDefault() - { - let SwitcherPopupProto = this._switcherPopup.SwitcherPopup.prototype; - - if (!SwitcherPopupProto.showOld) { - return; - } - - SwitcherPopupProto.show = SwitcherPopupProto.showOld; - delete(SwitcherPopupProto.showOld); - } - - /** - * enable the removal of switcher popup delay - * - * @returns {void} - */ - removeSwitcherPopupDelay() - { - let SwitcherPopupProto = this._switcherPopup.SwitcherPopup.prototype; - - SwitcherPopupProto.showOld = SwitcherPopupProto.show; - - SwitcherPopupProto.show = function (...args) { - let res = this.showOld(...args); - if (res) { - this._showImmediately(); - } - return res; - }; - } - - /** - * set default OSD position - * - * @returns {void} - */ - osdPositionSetDefault() - { - if (!this.#originals['osdWindowShow']) { - return; - } - - let osdWindowProto = this._osdWindow.OsdWindow.prototype; - - osdWindowProto.show = this.#originals['osdWindowShow']; - - delete(osdWindowProto._oldShow); - delete(this.#originals['osdWindowShow']); - - if ( - this.#originals['osdWindowXAlign'] !== undefined && - this.#originals['osdWindowYAlign'] !== undefined - ) { - let osdWindows = this._main.osdWindowManager._osdWindows; - osdWindows.forEach(osdWindow => { - osdWindow.x_align = this.#originals['osdWindowXAlign']; - osdWindow.y_align = this.#originals['osdWindowYAlign']; - }); - delete(this.#originals['osdWindowXAlign']); - delete(this.#originals['osdWindowYAlign']); - } - - this.UIStyleClassRemove(this.#getAPIClassname('osd-position-top')); - this.UIStyleClassRemove(this.#getAPIClassname('osd-position-bottom')); - this.UIStyleClassRemove(this.#getAPIClassname('osd-position-center')); - } - - /** - * set OSD position - * - * @param int pos position XY_POSITION - * - * @returns {void} - */ - osdPositionSet(pos) - { - let osdWindowProto = this._osdWindow.OsdWindow.prototype; - - if (!this.#originals['osdWindowShow']) { - this.#originals['osdWindowShow'] = osdWindowProto.show; - } - - if ( - this.#originals['osdWindowXAlign'] === undefined || - this.#originals['osdWindowYAlign'] === undefined - ) { - let osdWindows = this._main.osdWindowManager._osdWindows; - this.#originals['osdWindowXAlign'] = osdWindows[0].x_align; - this.#originals['osdWindowYAlign'] = osdWindows[0].y_align; - } - - if (osdWindowProto._oldShow === undefined) { - osdWindowProto._oldShow = this.#originals['osdWindowShow']; - } - - let [xAlign, yAlign] = this.#xyAlignGet(pos); - osdWindowProto.show = function () { - this.x_align = xAlign; - this.y_align = yAlign; - this._oldShow(); - }; - - if ( - pos === XY_POSITION.TOP_START || - pos === XY_POSITION.TOP_CENTER || - pos === XY_POSITION.TOP_END - ) { - this.UIStyleClassAdd(this.#getAPIClassname('osd-position-top')); - } - - if ( - pos === XY_POSITION.BOTTOM_START || - pos === XY_POSITION.BOTTOM_CENTER || - pos === XY_POSITION.BOTTOM_END - ) { - this.UIStyleClassAdd(this.#getAPIClassname('osd-position-bottom')); - } - - if ( - pos === XY_POSITION.CENTER_START || - pos === XY_POSITION.CENTER_CENTER || - pos === XY_POSITION.CENTER_END - ) { - this.UIStyleClassAdd(this.#getAPIClassname('osd-position-center')); - } - } - - /** - * show weather in date menu - * - * @returns {void} - */ - weatherShow() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-weather')); - } - - /** - * hide weather in date menu - * - * @returns {void} - */ - weatherHide() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-weather')); - } - - /** - * show world clocks in date menu - * - * @returns {void} - */ - worldClocksShow() - { - if (!this.#originals['clocksItemSync']) { - return; - } - - let clocksItem = this._main.panel.statusArea.dateMenu._clocksItem; - - clocksItem._sync = this.#originals['clocksItemSync']; - delete(this.#originals['clocksItemSync']); - - if (this._clocksItemShowSignal) { - clocksItem.disconnect(this._clocksItemShowSignal); - delete(this._clocksItemShowSignal); - } - - clocksItem._sync(); - } - - /** - * hide world clocks in date menu - * - * @returns {void} - */ - worldClocksHide() - { - let clocksItem = this._main.panel.statusArea.dateMenu._clocksItem; - - if (!this.#originals['clocksItemSync']) { - this.#originals['clocksItemSync'] = clocksItem._sync; - } - - clocksItem._sync = function () { - this.visible = false; - }; - - if (!this._clocksItemShowSignal) { - this._clocksItemShowSignal = clocksItem.connect('show', () => { - clocksItem._sync(); - }); - } - - clocksItem._sync(); - } - - /** - * show events button in date menu - * - * @returns {void} - */ - eventsButtonShow() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-events-button')); - } - - /** - * hide events button in date menu - * - * @returns {void} - */ - eventsButtonHide() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-events-button')); - } - - /** - * show calendar in date menu - * - * @returns {void} - */ - calendarShow() - { - this._main.panel.statusArea.dateMenu._calendar.show(); - } - - /** - * hide calendar in date menu - * - * @returns {void} - */ - calendarHide() - { - this._main.panel.statusArea.dateMenu._calendar.hide(); - } - - /** - * set default panel icon size - * - * @returns {void} - */ - panelIconSetDefaultSize() - { - if (this._panelIconSize === undefined || !this.#originals['panelIconSize']) { - return; - } - - let classnameStarter = this.#getAPIClassname('panel-icon-size'); - this.UIStyleClassRemove(classnameStarter + this._panelIconSize); - this.#emitRefreshStyles(); - - let defaultSize = this.#originals['panelIconSize']; - this.#changeDateMenuIndicatorIconSize(defaultSize); - - delete(this._panelIconSize); - } - - /** - * set panel icon size - * - * @param {number} size 1-60 - * - * @returns {void} - */ - panelIconSetSize(size) - { - if (size < 1 || size > 60) { - return; - } - - if (!this.#originals['panelIconSize']) { - this.#originals['panelIconSize'] = this._panel.PANEL_ICON_SIZE; - } - - let classnameStarter = this.#getAPIClassname('panel-icon-size'); - this.UIStyleClassRemove(classnameStarter + this.panelIconGetSize()); - this.UIStyleClassAdd(classnameStarter + size); - this.#emitRefreshStyles(); - - this.#changeDateMenuIndicatorIconSize(size); - - this._panelIconSize = size; - } - - /** - * change date menu indicator icon size - * - * @param {number} size - * - * @returns {void} - */ - #changeDateMenuIndicatorIconSize(size) - { - let dateMenu = this._main.panel.statusArea.dateMenu; - - // we get set_icon_size is not a function in some setups - // in case the date menu has been removed or not created - if ( - dateMenu && - dateMenu._indicator && - dateMenu._indicator.set_icon_size - ) { - dateMenu._indicator.set_icon_size(size); - } - } - - /** - * get panel icon size - * - * @returns {void} - */ - panelIconGetSize() - { - if (this._panelIconSize !== undefined) { - return this._panelIconSize; - } - - return this._panel.PANEL_ICON_SIZE; - } - - /** - * show dash separator - * - * @returns {void} - */ - dashSeparatorShow() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-dash-separator')); - } - - /** - * hide dash separator - * - * @returns {void} - */ - dashSeparatorHide() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-dash-separator')); - } - - /** - * get looking glass size - * - * @returns {array} - * width: int - * height: int - */ - #lookingGlassGetSize() - { - let lookingGlass = this._main.createLookingGlass(); - - return [lookingGlass.width, lookingGlass.height]; - } - - /** - * set default looking glass size - * - * @returns {void} - */ - lookingGlassSetDefaultSize() - { - if (!this._lookingGlassShowSignal) { - return; - } - - this._main.lookingGlass.disconnect(this._lookingGlassShowSignal); - - delete(this._lookingGlassShowSignal); - delete(this._lookingGlassOriginalSize); - delete(this._monitorsChangedSignal); - } - - /** - * set looking glass size - * - * @param {number} width in float - * @param {number} height in float - * - * @returns {void} - */ - lookingGlassSetSize(width, height) - { - let lookingGlass = this._main.createLookingGlass(); - - if (!this._lookingGlassOriginalSize) { - this._lookingGlassOriginalSize = this.#lookingGlassGetSize(); - } - - if (this._lookingGlassShowSignal) { - lookingGlass.disconnect(this._lookingGlassShowSignal); - delete(this._lookingGlassShowSignal); - } - - this._lookingGlassShowSignal = lookingGlass.connect('show', () => { - let [, currentHeight] = this.#lookingGlassGetSize(); - let [originalWidth, originalHeight] = this._lookingGlassOriginalSize; - - let monitorInfo = this.monitorGetInfo(); - - let dialogWidth - = (width !== null) - ? monitorInfo.width * width - : originalWidth; - - let x = monitorInfo.x + (monitorInfo.width - dialogWidth) / 2; - lookingGlass.set_x(x); - - let keyboardHeight = this._main.layoutManager.keyboardBox.height; - let availableHeight = monitorInfo.height - keyboardHeight; - let dialogHeight - = (height !== null) - ? Math.min(monitorInfo.height * height, availableHeight * 0.9) - : originalHeight; - - let hiddenY = lookingGlass._hiddenY + currentHeight - dialogHeight; - lookingGlass.set_y(hiddenY); - lookingGlass._hiddenY = hiddenY; - - lookingGlass.set_size(dialogWidth, dialogHeight); - }); - - if (!this._monitorsChangedSignal) { - this._monitorsChangedSignal = this._main.layoutManager.connect('monitors-changed', - () => { - this.lookingGlassSetSize(width, height); - }); - } - } - - /** - * show screenshot in window menu - * - * @returns {void} - */ - screenshotInWindowMenuShow() - { - let windowMenuProto = this._windowMenu.WindowMenu.prototype; - - if (windowMenuProto._oldBuildMenu === undefined) { - return; - } - - windowMenuProto._buildMenu = this.#originals['WindowMenubuildMenu']; - - delete(windowMenuProto._oldBuildMenu); - } - - /** - * hide screenshot in window menu - * - * @returns {void} - */ - screenshotInWindowMenuHide() - { - let windowMenuProto = this._windowMenu.WindowMenu.prototype; - - if (!this.#originals['WindowMenubuildMenu']) { - this.#originals['WindowMenubuildMenu'] = windowMenuProto._buildMenu; - } - - if (windowMenuProto._oldBuildMenu === undefined) { - windowMenuProto._oldBuildMenu = this.#originals['WindowMenubuildMenu']; - } - - windowMenuProto._buildMenu = function (window) { - this._oldBuildMenu(window); - this.firstMenuItem.hide(); - }; - } - - /** - * set all alt tab sizes to default - * - * @returns {void} - */ - #altTabSizesSetDefault() - { - let WindowIconProto = this._altTab.WindowIcon.prototype; - if (WindowIconProto._initOld) { - WindowIconProto._init = WindowIconProto._initOld; - delete(WindowIconProto._initOld); - } - - delete(this._altTabAPP_ICON_SIZE); - delete(this._altTabAPP_ICON_SIZE_SMALL); - delete(this._altTabWINDOW_PREVIEW_SIZE); - } - - /** - * set alt tab sizes - * - * @param {number|null} appIconSize - * @param {number|null} appIconSizeSmall - * @param {number|null} windowPreviewSize - * - * @returns {void} - */ - #altTabSizesSet(appIconSize, appIconSizeSmall, windowPreviewSize) - { - let WindowIconProto = this._altTab.WindowIcon.prototype; - if (!WindowIconProto._initOld) { - WindowIconProto._initOld = WindowIconProto._init; - } - - this._altTabAPP_ICON_SIZE ||= this._altTab.APP_ICON_SIZE; - this._altTabAPP_ICON_SIZE_SMALL ||= this._altTab.APP_ICON_SIZE_SMALL; - this._altTabWINDOW_PREVIEW_SIZE ||= this._altTab.WINDOW_PREVIEW_SIZE; - - const APP_ICON_SIZE = appIconSize || this._altTabAPP_ICON_SIZE; - const APP_ICON_SIZE_SMALL = appIconSizeSmall || this._altTabAPP_ICON_SIZE_SMALL; - const WINDOW_PREVIEW_SIZE = windowPreviewSize || this._altTabWINDOW_PREVIEW_SIZE; - - WindowIconProto._init = function(window, mode) { - this._initOld(window, mode); - } - } - - /** - * set default alt tab window preview size - * - * @returns {void} - */ - altTabWindowPreviewSetDefaultSize() - { - if (!this.#originals['altTabWindowPreviewSize']) { - return; - } - - this.#altTabSizesSet(null, null, this.#originals['altTabWindowPreviewSize']); - } - - /** - * set alt tab window preview size - * - * @param {number} size 1-512 - * - * @returns {void} - */ - altTabWindowPreviewSetSize(size) - { - if (size < 1 || size > 512) { - return; - } - - if (!this.#originals['altTabWindowPreviewSize']) { - this.#originals['altTabWindowPreviewSize'] = this._altTab.WINDOW_PREVIEW_SIZE; - } - - this.#altTabSizesSet(null, null, size); - } - - /** - * set default alt tab small icon size - * - * @returns {void} - */ - altTabSmallIconSetDefaultSize() - { - if (!this.#originals['altTabAppIconSizeSmall']) { - return; - } - - this.#altTabSizesSet(null, this.#originals['altTabAppIconSizeSmall'], null); - } - - /** - * set alt tab small icon size - * - * @param {number} size 1-512 - * - * @returns {void} - */ - altTabSmallIconSetSize(size) - { - if (size < 1 || size > 512) { - return; - } - - if (!this.#originals['altTabAppIconSizeSmall']) { - this.#originals['altTabAppIconSizeSmall'] = this._altTab.APP_ICON_SIZE_SMALL; - } - - this.#altTabSizesSet(null, size, null); - } - - /** - * set default alt tab icon size - * - * @returns {void} - */ - altTabIconSetDefaultSize() - { - if (!this.#originals['altTabAppIconSize']) { - return; - } - - this.#altTabSizesSet(this.#originals['altTabAppIconSize'], null, null); - } - - /** - * set alt tab icon size - * - * @param {number} size 1-512 - * - * @returns {void} - */ - altTabIconSetSize(size) - { - if (size < 1 || size > 512) { - return; - } - - if (!this.#originals['altTabAppIconSize']) { - this.#originals['altTabAppIconSize'] = this._altTab.APP_ICON_SIZE; - } - - this.#altTabSizesSet(size, null, null); - } - - /** - * enable screen sharing indicator - * - * @returns {void} - */ - screenSharingIndicatorEnable() - { - if (this.#shellVersion < 43) { - return; - } - - this.UIStyleClassRemove(this.#getAPIClassname('no-screen-sharing-indicator')); - } - - /** - * disable screen sharing indicator - * - * @returns {void} - */ - screenSharingIndicatorDisable() - { - if (this.#shellVersion < 43) { - return; - } - - this.UIStyleClassAdd(this.#getAPIClassname('no-screen-sharing-indicator')); - } - - /** - * enable screen recording indicator - * - * @returns {void} - */ - screenRecordingIndicatorEnable() - { - if (this.#shellVersion < 43) { - return; - } - - this.UIStyleClassRemove(this.#getAPIClassname('no-screen-recording-indicator')); - } - - /** - * disable screen recording indicator - * - * @returns {void} - */ - screenRecordingIndicatorDisable() - { - if (this.#shellVersion < 43) { - return; - } - - this.UIStyleClassAdd(this.#getAPIClassname('no-screen-recording-indicator')); - } - - /** - * set controls manager spacing to default - * - * @returns {void} - */ - controlsManagerSpacingSetDefault() - { - if (this._controlsManagerSpacingSize === undefined) { - return; - } - - let classnameStarter = this.#getAPIClassname('controls-manager-spacing-size'); - this.UIStyleClassRemove(classnameStarter + this._controlsManagerSpacingSize); - - delete this._controlsManagerSpacingSize; - } - - /** - * set controls manager spacing size - * - * @param {number} size in pixels (0 - 150) - * - * @returns {void} - */ - controlsManagerSpacingSizeSet(size) - { - this.controlsManagerSpacingSetDefault(); - - if (size < 0 || size > 150) { - return; - } - - this._controlsManagerSpacingSize = size; - - let classnameStarter = this.#getAPIClassname('controls-manager-spacing-size'); - this.UIStyleClassAdd(classnameStarter + size); - } - - /** - * set workspaces view spacing to default - * - * @returns {void} - */ - workspacesViewSpacingSetDefault() - { - let wsvp = this._workspacesView.WorkspacesView.prototype; - - if (wsvp._getSpacingOld === undefined) { - return; - } - - wsvp._getSpacing = wsvp._getSpacingOld; - delete wsvp._getSpacingOld; - } - - /** - * set workspaces view spacing size - * - * @param {number} size in pixels (0 - 500) - * - * @returns {void} - */ - workspacesViewSpacingSizeSet(size) - { - if (size < 0 || size > 500) { - return; - } - - let wsvp = this._workspacesView.WorkspacesView.prototype; - - if (wsvp._getSpacingOld === undefined) { - wsvp._getSpacingOld = wsvp._getSpacing; - } - - wsvp._getSpacing = function (box, fitMode, vertical) { - if (fitMode === 0) { - return size; - } - return this._getSpacingOld(box, fitMode, vertical); - }; - } - - /** - * show dash app running dot - * - * @returns {void} - */ - dashAppRunningDotShow() - { - this.UIStyleClassRemove(this.#getAPIClassname('no-dash-app-running-dot')); - } - - /** - * hide dash app running dot - * - * @returns {void} - */ - dashAppRunningDotHide() - { - this.UIStyleClassAdd(this.#getAPIClassname('no-dash-app-running-dot')); - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Manager.js b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Manager.js deleted file mode 100755 index 6b51f9fc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Manager.js +++ /dev/null @@ -1,1435 +0,0 @@ -/** - * Manager Library - * - * @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com> - * @copyright 2020-2024 - * @license GPL-3.0-only - */ - -/** - * Apply settings to the GNOME Shell - */ -export class Manager -{ - /** - * Current shell version - * - * @type {number|null} - */ - #shellVersion = null; - - /** - * Instance of API - * - * @type {API|null} - */ - #api = null; - - /** - * Instance of Gio.Settings - * - * @type {Settings|null} - */ - #settings = null; - - /** - * Class Constructor - * - * @param {Object} dependencies - * 'API' instance of lib::API - * 'Settings' instance of Gio::Settings - * @param {number} shellVersion float in major.minor format - */ - constructor(dependencies, shellVersion) - { - this.#api = dependencies['API'] || null; - this.#settings = dependencies['Settings'] || null; - - this.#shellVersion = shellVersion; - } - - /** - * register all signals for settings - * - * @returns {void} - */ - registerSettingsSignals() - { - this.#settings.connect('changed::panel', () => { - this.#applyPanel(false); - }); - - this.#settings.connect('changed::panel-in-overview', () => { - this.#applyPanel(false); - }); - - this.#settings.connect('changed::search', () => { - this.#applySearch(false); - }); - - this.#settings.connect('changed::dash', () => { - this.#applyDash(false); - }); - - this.#settings.connect('changed::osd', () => { - this.#applyOSD(false); - }); - - this.#settings.connect('changed::workspace-popup', () => { - this.#applyWorkspacePopup(false); - }); - - this.#settings.connect('changed::workspace', () => { - this.#applyWorkspace(false); - }); - - this.#settings.connect('changed::background-menu', () => { - this.#applyBackgroundMenu(false); - }); - - this.#settings.connect('changed::theme', () => { - this.#applyTheme(false); - }); - - this.#settings.connect('changed::activities-button', () => { - this.#applyActivitiesButton(false); - }); - - this.#settings.connect('changed::clock-menu', () => { - this.#applyClockMenu(false); - }); - - this.#settings.connect('changed::keyboard-layout', () => { - this.#applyKeyboardLayout(false); - }); - - this.#settings.connect('changed::accessibility-menu', () => { - this.#applyAccessibilityMenu(false); - }); - - this.#settings.connect('changed::quick-settings', () => { - this.#applyQuickSettings(false); - }); - - this.#settings.connect('changed::window-picker-icon', () => { - this.#applyWindowPickerIcon(false); - }); - - this.#settings.connect('changed::type-to-search', () => { - this.#applyTypeToSearch(false); - }); - - this.#settings.connect('changed::workspace-switcher-size', () => { - this.#applyWorkspaceSwitcherSize(false); - }); - - this.#settings.connect('changed::power-icon', () => { - this.#applyPowerIcon(false); - }); - - this.#settings.connect('changed::top-panel-position', () => { - this.#applyTopPanelPosition(false); - }); - - this.#settings.connect('changed::panel-notification-icon', () => { - this.#applyPanelNotificationIcon(false); - }); - - this.#settings.connect('changed::clock-menu-position', () => { - this.#applyClockMenuPosition(false); - }); - - this.#settings.connect('changed::clock-menu-position-offset', () => { - this.#applyClockMenuPosition(false); - }); - - this.#settings.connect('changed::show-apps-button', () => { - this.#applyShowAppsButton(false); - }); - - this.#settings.connect('changed::animation', () => { - this.#applyAnimation(false); - }); - - this.#settings.connect('changed::window-demands-attention-focus', () => { - this.#applyWindowDemandsAttentionFocus(false); - }); - - this.#settings.connect('changed::window-maximized-on-create', () => { - this.#applyWindowMaximizedOnCreate(false); - }); - - this.#settings.connect('changed::dash-icon-size', () => { - this.#applyDashIconSize(false); - }); - - this.#settings.connect('changed::startup-status', () => { - this.#applyStartupStatus(false); - }); - - this.#settings.connect('changed::workspaces-in-app-grid', () => { - this.#applyWorkspacesInAppGrid(false); - }); - - this.#settings.connect('changed::notification-banner-position', () => { - this.#applyNotificationBannerPosition(false); - }); - - this.#settings.connect('changed::workspace-switcher-should-show', () => { - this.#applyWorkspaceSwitcherShouldShow(false); - }); - - this.#settings.connect('changed::panel-size', () => { - this.#applyPanelSize(false); - }); - - this.#settings.connect('changed::panel-button-padding-size', () => { - this.#applyPanelButtonPaddingSize(false); - }); - - this.#settings.connect('changed::panel-indicator-padding-size', () => { - this.#applyPanelIndicatorPaddingSize(false); - }); - - this.#settings.connect('changed::window-preview-caption', () => { - this.#applyWindowPreviewCaption(false); - }); - - this.#settings.connect('changed::window-preview-close-button', () => { - this.#applyWindowPreviewCloseButton(false); - }); - - this.#settings.connect('changed::workspace-background-corner-size', () => { - this.#applyWorkspaceBackgroundCornerSize(false); - }); - - this.#settings.connect('changed::workspace-wrap-around', () => { - this.#applyWorkspaceWrapAround(false); - }); - - this.#settings.connect('changed::ripple-box', () => { - this.#applyRippleBox(false); - }); - - this.#settings.connect('changed::overlay-key', () => { - this.#applyOverlayKey(false); - }); - - this.#settings.connect('changed::double-super-to-appgrid', () => { - this.#applyOverlayKey(false); - }); - - this.#settings.connect('changed::switcher-popup-delay', () => { - this.#applySwitcherPopupDelay(false); - }); - - this.#settings.connect('changed::world-clock', () => { - this.#applyWorldClock(false); - }); - - this.#settings.connect('changed::weather', () => { - this.#applyWeather(false); - }); - - this.#settings.connect('changed::calendar', () => { - this.#applyCalendar(false); - }); - - this.#settings.connect('changed::events-button', () => { - this.#applyEventsButton(false); - }); - - this.#settings.connect('changed::panel-icon-size', () => { - this.#applyPanelIconSize(false); - }); - - this.#settings.connect('changed::dash-separator', () => { - this.#applyDashSeparator(false); - }); - - this.#settings.connect('changed::looking-glass-width', () => { - this.#applyLookingGlassSize(false); - }); - - this.#settings.connect('changed::looking-glass-height', () => { - this.#applyLookingGlassSize(false); - }); - - this.#settings.connect('changed::osd-position', () => { - this.#applyOSDPosition(false); - }); - - this.#settings.connect('changed::window-menu-take-screenshot-button', () => { - this.#applyWindowMenuTakeScreenshotButton(false); - }); - - this.#settings.connect('changed::alt-tab-window-preview-size', () => { - this.#applyAltTabWindowPreviewSize(false); - }); - - this.#settings.connect('changed::alt-tab-small-icon-size', () => { - this.#applyAltTabSmallIconSize(false); - }); - - this.#settings.connect('changed::alt-tab-icon-size', () => { - this.#applyAltTabIconSize(false); - }); - - this.#settings.connect('changed::screen-sharing-indicator', () => { - this.#applyScreenSharingIndicator(false); - }); - - this.#settings.connect('changed::screen-recording-indicator', () => { - this.#applyScreenRecordingIndicator(false); - }); - - this.#settings.connect('changed::controls-manager-spacing-size', () => { - this.#applyControlsManagerSpacingSize(false); - }); - - this.#settings.connect('changed::workspace-peek', () => { - this.#applyWorkspacePeek(false); - }); - - this.#settings.connect('changed::dash-app-running', () => { - this.#applyDashAppRunning(true); - }); - } - - /** - * apply everything to the GNOME Shell - * - * @returns {void} - */ - applyAll() - { - this.#applyTheme(false); - this.#applyPanel(false); - this.#applySearch(false); - this.#applyDash(false); - this.#applyOSD(false); - this.#applyWorkspacePopup(false); - this.#applyWorkspace(false); - this.#applyBackgroundMenu(false); - this.#applyActivitiesButton(false); - this.#applyClockMenu(false); - this.#applyKeyboardLayout(false); - this.#applyAccessibilityMenu(false); - this.#applyQuickSettings(false); - this.#applyWindowPickerIcon(false); - this.#applyTypeToSearch(false); - this.#applyWorkspaceSwitcherSize(false); - this.#applyPowerIcon(false); - this.#applyTopPanelPosition(false); - this.#applyPanelNotificationIcon(false); - this.#applyClockMenuPosition(false); - this.#applyShowAppsButton(false); - this.#applyAnimation(false); - this.#applyWindowDemandsAttentionFocus(false); - this.#applyWindowMaximizedOnCreate(false); - this.#applyDashIconSize(false); - this.#applyStartupStatus(false); - this.#applyWorkspacesInAppGrid(false); - this.#applyNotificationBannerPosition(false); - this.#applyWorkspaceSwitcherShouldShow(false); - this.#applyPanelSize(false); - this.#applyPanelButtonPaddingSize(false); - this.#applyPanelIndicatorPaddingSize(false); - this.#applyWindowPreviewCaption(false); - this.#applyWindowPreviewCloseButton(false); - this.#applyWorkspaceBackgroundCornerSize(false); - this.#applyWorkspaceWrapAround(false); - this.#applyRippleBox(false); - this.#applyOverlayKey(false); - this.#applySwitcherPopupDelay(false); - this.#applyWorldClock(false); - this.#applyWeather(false); - this.#applyPanelIconSize(false); - this.#applyEventsButton(false); - this.#applyCalendar(false); - this.#applyDashSeparator(false); - this.#applyLookingGlassSize(false); - this.#applyOSDPosition(false); - this.#applyWindowMenuTakeScreenshotButton(false); - this.#applyAltTabWindowPreviewSize(false); - this.#applyAltTabSmallIconSize(false); - this.#applyAltTabIconSize(false); - this.#applyScreenSharingIndicator(false); - this.#applyScreenRecordingIndicator(false); - this.#applyControlsManagerSpacingSize(false); - this.#applyWorkspacePeek(false); - this.#applyDashAppRunning(false); - } - - /** - * revert everything done by this class to the GNOME Shell - * - * @returns {void} - */ - revertAll() - { - this.#applyTheme(true); - this.#applyPanel(true); - this.#applySearch(true); - this.#applyDash(true); - this.#applyOSD(true); - this.#applyWorkspace(true); - this.#applyWorkspacePopup(true); - this.#applyBackgroundMenu(true); - this.#applyActivitiesButton(true); - this.#applyClockMenu(true); - this.#applyKeyboardLayout(true); - this.#applyAccessibilityMenu(true); - this.#applyQuickSettings(true); - this.#applyWindowPickerIcon(true); - this.#applyTypeToSearch(true); - this.#applyWorkspaceSwitcherSize(true); - this.#applyPowerIcon(true); - this.#applyTopPanelPosition(true); - this.#applyPanelNotificationIcon(true); - this.#applyClockMenuPosition(true); - this.#applyShowAppsButton(true); - this.#applyAnimation(true); - this.#applyWindowDemandsAttentionFocus(true); - this.#applyWindowMaximizedOnCreate(true); - this.#applyDashIconSize(true); - this.#applyStartupStatus(true); - this.#applyWorkspacesInAppGrid(true); - this.#applyNotificationBannerPosition(true); - this.#applyWorkspaceSwitcherShouldShow(true); - this.#applyPanelSize(true); - this.#applyPanelButtonPaddingSize(true); - this.#applyPanelIndicatorPaddingSize(true); - this.#applyWindowPreviewCaption(true); - this.#applyWindowPreviewCloseButton(true); - this.#applyWorkspaceBackgroundCornerSize(true); - this.#applyWorkspaceWrapAround(true); - this.#applyRippleBox(true); - this.#applyOverlayKey(true); - this.#applySwitcherPopupDelay(true); - this.#applyWorldClock(true); - this.#applyWeather(true); - this.#applyPanelIconSize(true); - this.#applyEventsButton(true); - this.#applyCalendar(true); - this.#applyDashSeparator(true); - this.#applyLookingGlassSize(true); - this.#applyOSDPosition(true); - this.#applyWindowMenuTakeScreenshotButton(true); - this.#applyAltTabWindowPreviewSize(true); - this.#applyAltTabSmallIconSize(true); - this.#applyAltTabIconSize(true); - this.#applyScreenSharingIndicator(true); - this.#applyScreenRecordingIndicator(true); - this.#applyControlsManagerSpacingSize(true); - this.#applyWorkspacePeek(true); - this.#applyDashAppRunning(true); - } - - /** - * apply panel settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPanel(forceOriginal) - { - let panel = this.#settings.get_boolean('panel'); - let panelInOverview = this.#settings.get_boolean('panel-in-overview'); - - if (forceOriginal || panel) { - this.#api.panelShow(); - } else { - let mode = (panelInOverview) ? 1 : 0; - this.#api.panelHide(mode); - } - } - - /** - * apply search settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applySearch(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('search')) { - this.#api.searchEntryShow(false); - } else { - this.#api.searchEntryHide(false); - } - } - - /** - * apply type to search settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyTypeToSearch(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('type-to-search')) { - this.#api.startSearchEnable(); - } else { - this.#api.startSearchDisable(); - } - } - - /** - * apply dash settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyDash(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('dash')) { - this.#api.dashShow(); - } else { - this.#api.dashHide(); - } - } - - /** - * apply osd settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyOSD(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('osd')) { - this.#api.OSDEnable(); - } else { - this.#api.OSDDisable(); - } - } - - /** - * apply workspace popup settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspacePopup(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('workspace-popup')) { - this.#api.workspacePopupEnable(); - } else { - this.#api.workspacePopupDisable(); - } - } - - /** - * apply workspace settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspace(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('workspace')) { - this.#api.workspaceSwitcherShow(); - } else { - this.#api.workspaceSwitcherHide(); - } - } - - /** - * apply background menu settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyBackgroundMenu(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('background-menu')) { - this.#api.backgroundMenuEnable(); - } else { - this.#api.backgroundMenuDisable(); - } - } - - /** - * apply theme settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyTheme(forceOriginal) - { - let className = 'just-perfection'; - - if (forceOriginal || !this.#settings.get_boolean('theme')) { - this.#api.UIStyleClassRemove(className); - } else { - this.#api.UIStyleClassAdd(className); - } - } - - /** - * apply activities button settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyActivitiesButton(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('activities-button')) { - this.#api.activitiesButtonShow(); - } else { - this.#api.activitiesButtonHide(); - } - } - - /** - * apply clock menu (aka date menu) settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyClockMenu(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('clock-menu')) { - this.#api.dateMenuShow(); - } else { - this.#api.dateMenuHide(); - } - } - - /** - * apply keyboard layout settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyKeyboardLayout(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('keyboard-layout')) { - this.#api.keyboardLayoutShow(); - } else { - this.#api.keyboardLayoutHide(); - } - } - - /** - * apply accessibility menu settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyAccessibilityMenu(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('accessibility-menu')) { - this.#api.accessibilityMenuShow(); - } else { - this.#api.accessibilityMenuHide(); - } - } - - /** - * apply quick settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyQuickSettings(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('quick-settings')) { - this.#api.quickSettingsMenuShow(); - } else { - this.#api.quickSettingsMenuHide(); - } - } - - /** - * apply window picker icon settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWindowPickerIcon(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('window-picker-icon')) { - this.#api.windowPickerIconEnable(); - } else { - this.#api.windowPickerIconDisable(); - } - } - - /** - * apply workspace switcher size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspaceSwitcherSize(forceOriginal) - { - let size = this.#settings.get_int('workspace-switcher-size'); - - if (forceOriginal || size === 0) { - this.#api.workspaceSwitcherSetDefaultSize(); - } else { - this.#api.workspaceSwitcherSetSize(size / 100); - } - } - - /** - * apply power icon settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPowerIcon(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('power-icon')) { - this.#api.powerIconShow(); - } else { - this.#api.powerIconHide(); - } - } - - /** - * apply top panel position settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyTopPanelPosition(forceOriginal) - { - if (forceOriginal || this.#settings.get_int('top-panel-position') === 0) { - this.#api.panelSetPosition(0); - } else { - this.#api.panelSetPosition(1); - } - } - - /** - * apply panel notification icon settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPanelNotificationIcon(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('panel-notification-icon')) { - this.#api.panelNotificationIconEnable(); - } else { - this.#api.panelNotificationIconDisable(); - } - } - - /** - * apply clock menu position settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyClockMenuPosition(forceOriginal) - { - if (forceOriginal) { - this.#api.clockMenuPositionSetDefault(); - } else { - let pos = this.#settings.get_int('clock-menu-position'); - let offset = this.#settings.get_int('clock-menu-position-offset'); - this.#api.clockMenuPositionSet(pos, offset); - } - } - - /** - * apply show apps button settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyShowAppsButton(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('show-apps-button')) { - this.#api.showAppsButtonEnable(); - } else { - this.#api.showAppsButtonDisable(); - } - } - - /** - * apply animation settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyAnimation(forceOriginal) - { - let animation = this.#settings.get_int('animation'); - - let factors = [ - 0.01, // almost none - 0.2, // fastest - 0.6, // faster - 0.8, // fast - 1.3, // slow - 1.6, // slower - 2.8, // slowest - ]; - - if (forceOriginal) { - this.#api.animationSpeedSetDefault(); - this.#api.enableAnimationsSetDefault(); - } else if (animation === 0) { - // disabled - this.#api.animationSpeedSetDefault(); - this.#api.enableAnimationsSet(false); - } else if (animation === 1) { - // default speed - this.#api.animationSpeedSetDefault(); - this.#api.enableAnimationsSet(true); - } else if (factors[animation - 2] !== undefined) { - // custom speed - this.#api.animationSpeedSet(factors[animation - 2]); - this.#api.enableAnimationsSet(true); - } - } - - /** - * apply window demands attention focus settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWindowDemandsAttentionFocus(forceOriginal) - { - let focus = this.#settings.get_boolean('window-demands-attention-focus'); - - if (forceOriginal || !focus) { - this.#api.windowDemandsAttentionFocusDisable(); - } else { - this.#api.windowDemandsAttentionFocusEnable(); - } - } - - /** - * apply window maximized on create settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWindowMaximizedOnCreate(forceOriginal) - { - let maximize = this.#settings.get_boolean('window-maximized-on-create'); - - if (forceOriginal || !maximize) { - this.#api.windowMaximizedOnCreateDisable(); - } else { - this.#api.windowMaximizedOnCreateEnable(); - } - } - - /** - * apply dash icon size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyDashIconSize(forceOriginal) - { - let size = this.#settings.get_int('dash-icon-size'); - - if (forceOriginal || size === 0) { - this.#api.dashIconSizeSetDefault(); - } else { - this.#api.dashIconSizeSet(size); - } - } - - /** - * apply startup status settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyStartupStatus(forceOriginal) - { - let status = this.#settings.get_int('startup-status'); - - if (forceOriginal) { - this.#api.startupStatusSetDefault(); - } else { - this.#api.startupStatusSet(status); - } - } - - /** - * apply workspaces in app grid status settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspacesInAppGrid(forceOriginal) - { - let status = this.#settings.get_boolean('workspaces-in-app-grid'); - - if (forceOriginal || status) { - this.#api.workspacesInAppGridEnable(); - } else { - this.#api.workspacesInAppGridDisable(); - } - } - - /** - * apply notification banner position settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyNotificationBannerPosition(forceOriginal) - { - let pos = this.#settings.get_int('notification-banner-position'); - - if (forceOriginal) { - this.#api.notificationBannerPositionSetDefault(); - } else { - this.#api.notificationBannerPositionSet(pos); - } - } - - /** - * apply workspace switcher should show settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspaceSwitcherShouldShow(forceOriginal) - { - let shouldShow = this.#settings.get_boolean('workspace-switcher-should-show'); - - if (forceOriginal || !shouldShow) { - this.#api.workspaceSwitcherShouldShowSetDefault(); - } else { - this.#api.workspaceSwitcherShouldShow(true); - } - } - - /** - * apply panel size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPanelSize(forceOriginal) - { - let size = this.#settings.get_int('panel-size'); - - if (forceOriginal || size === 0) { - this.#api.panelSetDefaultSize(); - } else { - this.#api.panelSetSize(size, false); - } - } - - /** - * apply panel button padding size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPanelButtonPaddingSize(forceOriginal) - { - let size = this.#settings.get_int('panel-button-padding-size'); - - if (forceOriginal || size === 0) { - this.#api.panelButtonHpaddingSetDefault(); - } else { - this.#api.panelButtonHpaddingSizeSet(size - 1); - } - } - - /** - * apply panel indicator padding size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPanelIndicatorPaddingSize(forceOriginal) - { - let size = this.#settings.get_int('panel-indicator-padding-size'); - - if (forceOriginal || size === 0) { - this.#api.panelIndicatorPaddingSetDefault(); - } else { - this.#api.panelIndicatorPaddingSizeSet(size - 1); - } - } - - /** - * apply window preview caption settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWindowPreviewCaption(forceOriginal) - { - let status = this.#settings.get_boolean('window-preview-caption'); - - if (forceOriginal || status) { - this.#api.windowPreviewCaptionEnable(); - } else { - this.#api.windowPreviewCaptionDisable(); - } - } - - /** - * apply window preview close button settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWindowPreviewCloseButton(forceOriginal) - { - let status = this.#settings.get_boolean('window-preview-close-button'); - - if (forceOriginal || status) { - this.#api.windowPreviewCloseButtonEnable(); - } else { - this.#api.windowPreviewCloseButtonDisable(); - } - } - - /** - * apply workspace background corner size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspaceBackgroundCornerSize(forceOriginal) - { - let size = this.#settings.get_int('workspace-background-corner-size'); - - if (forceOriginal || size === 0) { - this.#api.workspaceBackgroundRadiusSetDefault(); - } else { - this.#api.workspaceBackgroundRadiusSet(size - 1); - } - } - - /** - * apply workspace wrap around settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspaceWrapAround(forceOriginal) - { - let status = this.#settings.get_boolean('workspace-wrap-around'); - - if (forceOriginal || !status) { - this.#api.workspaceWraparoundDisable(); - } else { - this.#api.workspaceWraparoundEnable(); - } - } - - /** - * apply ripple box settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyRippleBox(forceOriginal) - { - let status = this.#settings.get_boolean('ripple-box'); - - if (forceOriginal || status) { - this.#api.rippleBoxEnable(); - } else { - this.#api.rippleBoxDisable(); - } - } - - /** - * apply overlay key - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyOverlayKey(forceOriginal) - { - let overlayKey = this.#settings.get_boolean('overlay-key'); - let doubleSuper = this.#settings.get_boolean('double-super-to-appgrid'); - - if (forceOriginal) { - this.#api.doubleSuperToAppGridEnable(); - this.#api.unblockOverlayKey(); - } else if (!overlayKey) { - this.#api.doubleSuperToAppGridEnable(); - this.#api.blockOverlayKey(); - } else { - this.#api.unblockOverlayKey(); - if (doubleSuper) { - this.#api.doubleSuperToAppGridEnable(); - } else { - this.#api.doubleSuperToAppGridDisable(); - } - } - } - - /** - * apply switcher popup delay settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applySwitcherPopupDelay(forceOriginal) - { - let status = this.#settings.get_boolean('switcher-popup-delay'); - - if (forceOriginal || status) { - this.#api.switcherPopupDelaySetDefault(); - } else { - this.#api.removeSwitcherPopupDelay(); - } - } - - /** - * apply world clock settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorldClock(forceOriginal) - { - let status = this.#settings.get_boolean('world-clock'); - - if (forceOriginal || status) { - this.#api.worldClocksShow(); - } else { - this.#api.worldClocksHide(); - } - } - - /** - * apply weather settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWeather(forceOriginal) - { - let status = this.#settings.get_boolean('weather'); - - if (forceOriginal || status) { - this.#api.weatherShow(); - } else { - this.#api.weatherHide(); - } - } - - /** - * apply calendar settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyCalendar(forceOriginal) - { - let status = this.#settings.get_boolean('calendar'); - - if (forceOriginal || status) { - this.#api.calendarShow(); - } else { - this.#api.calendarHide(); - } - } - - /** - * apply events button settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyEventsButton(forceOriginal) - { - let status = this.#settings.get_boolean('events-button'); - - if (forceOriginal || status) { - this.#api.eventsButtonShow(); - } else { - this.#api.eventsButtonHide(); - } - } - - /** - * apply panel icon size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyPanelIconSize(forceOriginal) - { - let size = this.#settings.get_int('panel-icon-size'); - - if (forceOriginal || size === 0) { - this.#api.panelIconSetDefaultSize(); - } else { - this.#api.panelIconSetSize(size); - } - } - - /** - * apply dash separator settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyDashSeparator(forceOriginal) - { - let status = this.#settings.get_boolean('dash-separator'); - - if (forceOriginal || status) { - this.#api.dashSeparatorShow(); - } else { - this.#api.dashSeparatorHide(); - } - } - - /** - * apply looking glass size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyLookingGlassSize(forceOriginal) - { - let widthSize = this.#settings.get_int('looking-glass-width'); - let heightSize = this.#settings.get_int('looking-glass-height'); - - if (forceOriginal) { - this.#api.lookingGlassSetDefaultSize(); - } else { - let width = (widthSize !== 0) ? widthSize / 10 : null; - let height = (heightSize !== 0) ? heightSize / 10 : null; - this.#api.lookingGlassSetSize(width, height); - } - } - - /** - * apply osd position settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyOSDPosition(forceOriginal) - { - let pos = this.#settings.get_int('osd-position'); - - if (forceOriginal || pos === 0) { - this.#api.osdPositionSetDefault(); - } else { - this.#api.osdPositionSet(pos - 1); - } - } - - /** - * apply window menu take screenshot button settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWindowMenuTakeScreenshotButton(forceOriginal) - { - let status = this.#settings.get_boolean('window-menu-take-screenshot-button'); - - if (forceOriginal || status) { - this.#api.screenshotInWindowMenuShow(); - } else { - this.#api.screenshotInWindowMenuHide(); - } - } - - /** - * apply alt tab window preview size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyAltTabWindowPreviewSize(forceOriginal) - { - let size = this.#settings.get_int('alt-tab-window-preview-size'); - - if (forceOriginal || size === 0) { - this.#api.altTabWindowPreviewSetDefaultSize(); - } else { - this.#api.altTabWindowPreviewSetSize(size); - } - } - - /** - * apply alt tab small icon size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyAltTabSmallIconSize(forceOriginal) - { - let size = this.#settings.get_int('alt-tab-small-icon-size'); - - if (forceOriginal || size === 0) { - this.#api.altTabSmallIconSetDefaultSize(); - } else { - this.#api.altTabSmallIconSetSize(size); - } - } - - /** - * apply alt tab icon size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyAltTabIconSize(forceOriginal) - { - let size = this.#settings.get_int('alt-tab-icon-size'); - - if (forceOriginal || size === 0) { - this.#api.altTabIconSetDefaultSize(); - } else { - this.#api.altTabIconSetSize(size); - } - } - - /** - * apply screen sharing indicator settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyScreenSharingIndicator(forceOriginal) - { - let status = this.#settings.get_boolean('screen-sharing-indicator'); - - if (forceOriginal || status) { - this.#api.screenSharingIndicatorEnable(); - } else { - this.#api.screenSharingIndicatorDisable(); - } - } - - /** - * apply screen recording indicator settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyScreenRecordingIndicator(forceOriginal) - { - let status = this.#settings.get_boolean('screen-recording-indicator'); - - if (forceOriginal || status) { - this.#api.screenRecordingIndicatorEnable(); - } else { - this.#api.screenRecordingIndicatorDisable(); - } - } - - /** - * apply controls manager spacing size settings - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyControlsManagerSpacingSize(forceOriginal) - { - let size = this.#settings.get_int('controls-manager-spacing-size'); - - if (forceOriginal || size === 0) { - this.#api.controlsManagerSpacingSetDefault(); - } else { - this.#api.controlsManagerSpacingSizeSet(size); - } - } - - /** - * apply workspace peek - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyWorkspacePeek(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('workspace-peek')) { - this.#api.workspacesViewSpacingSetDefault(); - } else { - this.#api.workspacesViewSpacingSizeSet(400); - } - } - - /** - * apply dash app running - * - * @param {boolean} forceOriginal force original shell setting - * - * @returns {void} - */ - #applyDashAppRunning(forceOriginal) - { - if (forceOriginal || this.#settings.get_boolean('dash-app-running')) { - this.#api.dashAppRunningDotShow(); - } else { - this.#api.dashAppRunningDotHide(); - } - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js deleted file mode 100755 index 48467308..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Prefs/Prefs.js +++ /dev/null @@ -1,338 +0,0 @@ -/** - * Prefs Library - * - * @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com> - * @copyright 2020-2024 - * @license GPL-3.0-only - */ - -/** - * prefs widget for showing prefs window - */ -export class Prefs -{ - /** - * Current shell version - * - * @type {number|null} - */ - #shellVersion = null; - - /** - * Instance of PrefsKeys - * - * @type {PrefsKeys|null} - */ - #prefsKeys = null; - - /** - * Instance of Gtk.Builder - * - * @type {Gtk.Builder|null} - */ - #builder = null; - - /** - * Instance of Gio.Settings - * - * @type {Settings|null} - */ - #settings = null; - - /** - * Instance of Gdk - * - * @type {Gdk|null} - */ - #gdk = null; - - /** - * All available profile names - * - * @type {Array} - */ - #profiles = [ - 'default', - 'minimal', - 'superminimal', - ]; - - /** - * class constructor - * - * @param {Object} dependencies - * 'Builder' instance of Gtk::Builder - * 'Settings' instance of Gio::Settings - * 'Gdk' reference to Gdk - * 'GLib' reference to GLib - * @param {PrefsKeys.PrefsKeys} prefsKeys instance of PrefsKeys - * @param {number} shellVersion float in major.minor format - */ - constructor(dependencies, prefsKeys, shellVersion) - { - this.#settings = dependencies['Settings'] || null; - this.#builder = dependencies['Builder'] || null; - this.#gdk = dependencies['Gdk'] || null; - - this.#prefsKeys = prefsKeys; - this.#shellVersion = shellVersion; - } - - /** - * fill prefs window - * - * @param {string} UIFolderPath folder path to ui folder - * @param {string} gettextDomain gettext domain - * - * @returns {void} - */ - fillPrefsWindow(window, UIFolderPath, gettextDomain) - { - // changing the order here can change the elements order in ui - let uiFilenames = [ - 'profile', - 'visibility', - 'icons', - 'behavior', - 'customize', - ]; - - this.#builder.set_translation_domain(gettextDomain); - for (let uiFilename of uiFilenames) { - this.#builder.add_from_file(`${UIFolderPath}/adw/${uiFilename}.ui`); - } - - for (let uiFilename of uiFilenames) { - let page = this.#builder.get_object(uiFilename); - window.add(page); - } - - this.#setValues(); - this.#guessProfile(); - this.#onlyShowSupportedRows(); - this.#registerAllSignals(window); - - this.#setWindowSize(window); - - window.search_enabled = true; - } - - /** - * set window size - * - * @param {Adw.PreferencesWindow} window prefs window - * - * @returns {void} - */ - #setWindowSize(window) - { - let [pmWidth, pmHeight, pmScale] = this.#getPrimaryMonitorInfo(); - let sizeTolerance = 50; - let width = 600; - let height = 650; - - if ( - (pmWidth / pmScale) - sizeTolerance >= width && - (pmHeight / pmScale) - sizeTolerance >= height - ) { - window.set_default_size(width, height); - } - } - - /** - * get primary monitor info - * - * @returns {Array} [width, height, scale] - */ - #getPrimaryMonitorInfo() - { - let display = this.#gdk.Display.get_default(); - - let pm = display.get_monitors().get_item(0); - - if (!pm) { - return [700, 500, 1]; - } - - let geo = pm.get_geometry(); - let scale = pm.get_scale_factor(); - - return [geo.width, geo.height, scale]; - } - - /** - * register all signals - * - * @param {Adw.PreferencesWindow} window prefs dialog - * - * @returns {void} - */ - #registerAllSignals(window) - { - this.#registerKeySignals(); - this.#registerProfileSignals(); - } - - /** - * register signals of all prefs keys - * - * @returns {void} - */ - #registerKeySignals() - { - // all available keys - for (let [, key] of Object.entries(this.#prefsKeys.keys)) { - - switch (key.widgetType) { - - case 'GtkSwitch': - this.#builder.get_object(key.widgetId).connect('state-set', (w) => { - this.#settings.set_boolean(key.name, w.get_active()); - this.#guessProfile(); - }); - break; - - case 'AdwActionRow': - this.#builder.get_object(key.widgetId).connect('notify::selected-item', (w) => { - let index = w.get_selected(); - let value = (index in key.maps) ? key.maps[index] : index; - this.#settings.set_int(key.name, value); - this.#guessProfile(); - }); - break; - } - } - } - - /** - * register profile signals - * - * @returns {void} - */ - #registerProfileSignals() - { - for (let profile of this.#profiles) { - let widget = this.#builder.get_object(`profile_${profile}`); - if (!widget) { - break; - } - widget.connect('clicked', (w) => { - this.#setValues(profile); - }); - } - } - - /** - * can check all current values and guess the profile based on the values - * - * @returns {void} - */ - #guessProfile() - { - let totalCount = 0; - let matchCount = {}; - - for (let profile of this.#profiles) { - matchCount[profile] = 0; - } - - for (let [, key] of Object.entries(this.#prefsKeys.keys)) { - - if (!key.supported) { - continue; - } - - let value; - - switch (key.widgetType) { - case 'GtkSwitch': - value = this.#builder.get_object(key.widgetId).get_active(); - break; - case 'AdwActionRow': - value = this.#builder.get_object(key.widgetId).get_selected(); - break; - default: - value = ''; - continue; - } - - for (let profile of this.#profiles) { - if (key.profiles[profile] === value) { - matchCount[profile]++; - } - } - - totalCount++; - } - - let currentProfile = 'custom'; - for (let profile of this.#profiles) { - if (matchCount[profile] === totalCount) { - currentProfile = profile; - break; - } - } - - let widget = this.#builder.get_object(`profile_${currentProfile}`); - if (widget) { - widget.set_active(true); - } - } - - /** - * set values for all elements - * - * @param {string} profile profile name or null for get it from gsettings - * - * @returns {void} - */ - #setValues(profile) - { - for (let [, key] of Object.entries(this.#prefsKeys.keys)) { - - let widget = this.#builder.get_object(key.widgetId); - - switch (key.widgetType) { - - case 'GtkSwitch': - let value - = (profile) - ? key.profiles[profile] - : this.#settings.get_boolean(key.name); - - widget.set_active(value); - break; - - case 'AdwActionRow': - let index - = (profile) - ? key.profiles[profile] - : this.#settings.get_int(key.name); - - for (let k in key.maps) { - if (key.maps[k] === index) { - index = k; - break; - } - } - widget.set_selected(index); - break; - } - } - } - - /** - * apply all supported keys to the elements - * - * @returns {void} - */ - #onlyShowSupportedRows() - { - for (let [, key] of Object.entries(this.#prefsKeys.keys)) { - let row = this.#builder.get_object(`${key.id}_row`); - let visible = key.supported; - row.visible = visible; - } - } -}; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Prefs/PrefsKeys.js b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Prefs/PrefsKeys.js deleted file mode 100755 index 6e4da9f7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/lib/Prefs/PrefsKeys.js +++ /dev/null @@ -1,858 +0,0 @@ -/** - * PrefsKeys Library - * - * @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com> - * @copyright 2020-2024 - * @license GPL-3.0-only - */ - -/** - * prefs keys - */ -export class PrefsKeys -{ - /** - * Current shell version - * - * @type {number|null} - */ - #shellVersion = null; - - /** - * class constructor - * - * @param {number} shellVersion float in major.minor format - */ - constructor(shellVersion) - { - this.#shellVersion = shellVersion; - - /** - * holds all keys generated by this.#setKey() - * - * @member {Object} - */ - this.keys = {}; - - this.#setDefaults(); - } - - /** - * set all default keys - * - * @returns {void} - */ - #setDefaults() - { - this.#setKey( - 'visibility', - 'panel', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'panel-in-overview', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'activities-button', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'clock-menu', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'keyboard-layout', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'accessibility-menu', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'quick-settings', - 'GtkSwitch', - this.#shellVersion >= 43, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'screen-sharing-indicator', - 'GtkSwitch', - this.#shellVersion >= 43, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'screen-recording-indicator', - 'GtkSwitch', - this.#shellVersion >= 43, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'search', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'dash', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'dash-separator', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'dash-app-running', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'osd', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'workspace-popup', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'workspace', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'background-menu', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'show-apps-button', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'workspaces-in-app-grid', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'window-preview-caption', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'window-preview-close-button', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'ripple-box', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'visibility', - 'world-clock', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'weather', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'calendar', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'events-button', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'visibility', - 'window-menu-take-screenshot-button', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'icons', - 'panel-notification-icon', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'icons', - 'power-icon', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'icons', - 'window-picker-icon', - 'GtkSwitch', - true, - { - default: true, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'behavior', - 'type-to-search', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'behavior', - 'window-demands-attention-focus', - 'GtkSwitch', - true, - { - default: false, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'behavior', - 'window-maximized-on-create', - 'GtkSwitch', - true, - { - default: false, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'behavior', - 'workspace-switcher-should-show', - 'GtkSwitch', - true, - { - default: false, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'behavior', - 'startup-status', - 'AdwActionRow', - true, - { - default: 1, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'behavior', - 'workspace-wrap-around', - 'GtkSwitch', - true, - { - default: false, - minimal: false, - superminimal: false, - } - ); - - this.#setKey( - 'behavior', - 'workspace-peek', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'behavior', - 'overlay-key', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'behavior', - 'double-super-to-appgrid', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: false, - } - ); - - this.#setKey( - 'behavior', - 'switcher-popup-delay', - 'GtkSwitch', - true, - { - default: true, - minimal: true, - superminimal: true, - } - ); - - this.#setKey( - 'customize', - 'controls-manager-spacing-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 22, - } - ); - - this.#setKey( - 'customize', - 'workspace-background-corner-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 15, - } - ); - - this.#setKey( - 'customize', - 'top-panel-position', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'clock-menu-position', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'clock-menu-position-offset', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'workspace-switcher-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'animation', - 'AdwActionRow', - true, - { - default: 1, - minimal: 1, - superminimal: 1, - } - ); - - this.#setKey( - 'customize', - 'dash-icon-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 1, - superminimal: 0, - }, - { - '1': 16, - '2': 22, - '3': 24, - '4': 32, - '5': 40, - '6': 48, - '7': 56, - '8': 64, - } - ); - - this.#setKey( - 'customize', - 'notification-banner-position', - 'AdwActionRow', - true, - { - default: 1, - minimal: 1, - superminimal: 1, - } - ); - - this.#setKey( - 'customize', - 'panel-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'panel-button-padding-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'panel-indicator-padding-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'panel-icon-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'osd-position', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'looking-glass-width', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'looking-glass-height', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - } - ); - - this.#setKey( - 'customize', - 'alt-tab-window-preview-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - }, - { - '0': 0, - '1': 32, - '2': 64, - '3': 128, - '4': 256, - '5': 512, - } - ); - - this.#setKey( - 'customize', - 'alt-tab-small-icon-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - }, - { - '0': 0, - '1': 32, - '2': 64, - '3': 128, - '4': 256, - '5': 512, - } - ); - - this.#setKey( - 'customize', - 'alt-tab-icon-size', - 'AdwActionRow', - true, - { - default: 0, - minimal: 0, - superminimal: 0, - }, - { - '0': 0, - '1': 32, - '2': 64, - '3': 128, - '4': 256, - '5': 512, - } - ); - - this.#setKey( - 'override', - 'theme', - 'GtkSwitch', - true, - { - default: false, - minimal: true, - superminimal: true, - } - ); - } - - /** - * set key - * - * @param {string} category possible values: - * - visibility - * - icons - * - behavior - * - customize - * - override - * @param {string} name should be the same as gsettings key name - * @param {string} widgetType gtk widget type like 'GtkSwitch'. - * @param {boolean} supported whether supported in the current shell - * @param {Object} profiles values for each profile. for example: - * {default: true, minimal: false} - * @param {Object} [maps] for example for combobox you can specify - * if the index is 1 use 32 as value: - * {1 : 32} - * - * @returns {Object} key object that has been set - */ - #setKey(category, name, widgetType, supported, profiles, maps) - { - let id = name.replace(/-/g, '_'); - let widgetName = widgetType.toLowerCase().replace('gtk', ''); - let widgetId = (widgetType === 'AdwActionRow') ? `${id}_row` : `${id}_${widgetName}`; - - if (maps === undefined) { - maps = {}; - } - - this.keys[id] = { - category, - widgetType, - name, - id, - widgetId, - supported, - profiles, - maps, - } - - return this.keys[id]; - } - - /** - * delete key - * - * @param {string} id key id - * - * @returns {void} - */ - deleteKey(id) - { - delete(this.keys[id]); - } -}; - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/af/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/af/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 6d942127..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/af/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ar/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ar/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 1a8cb7c6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ar/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/be/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/be/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index b34b1609..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/be/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/bg/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/bg/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 11f1ccd5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/bg/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ca/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ca/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index dca94722..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ca/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/de/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/de/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index b9022e27..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/de/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/es/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/es/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index c531b7df..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/es/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/fr/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/fr/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 8f5e660b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/fr/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/gl/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/gl/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 5c15f07f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/gl/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/it/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/it/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 33289a79..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/it/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ja/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ja/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 003a4e79..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ja/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ne/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ne/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 4a21dd05..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ne/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/nl/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/nl/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 1e7ecf5a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/nl/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/pt_BR/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/pt_BR/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 41f94400..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/pt_BR/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ru/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ru/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index f71bdf76..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/ru/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/sv/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/sv/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 3013fa7f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/sv/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/zh_CN/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/zh_CN/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index a8f1adec..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/zh_CN/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/zh_TW/LC_MESSAGES/just-perfection.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/zh_TW/LC_MESSAGES/just-perfection.mo deleted file mode 100755 index 8d776dbc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/locale/zh_TW/LC_MESSAGES/just-perfection.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/metadata.json deleted file mode 100755 index c2763cb2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Tweak Tool to Customize GNOME Shell, Change the Behavior and Disable UI Elements", - "donations": { - "buymeacoffee": "justperfection", - "patreon": "justperfection" - }, - "gettext-domain": "just-perfection", - "name": "Just Perfection", - "settings-schema": "org.gnome.shell.extensions.just-perfection", - "shell-version": [ - "45", - "46" - ], - "url": "https://gitlab.gnome.org/jrahmatzadeh/just-perfection", - "uuid": "just-perfection-desktop@just-perfection", - "version": 28 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/prefs.js deleted file mode 100755 index 01a7bbf2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/prefs.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Prefs Dialog - * - * @author Javad Rahmatzadeh <j.rahmatzadeh@gmail.com> - * @copyright 2020-2024 - * @license GPL-3.0-only - */ - -import Gtk from 'gi://Gtk'; -import Gdk from 'gi://Gdk'; - -import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; -import * as Config from 'resource:///org/gnome/Shell/Extensions/js/misc/config.js'; - -import {Prefs} from './lib/Prefs/Prefs.js'; -import {PrefsKeys} from './lib/Prefs/PrefsKeys.js'; - -/** - * Preferences window entry point - */ -export default class JustPerfectionPrefs extends ExtensionPreferences -{ - /** - * fill preferences window - * - * @returns {void} - */ - fillPreferencesWindow(window) - { - const shellVersion = parseFloat(Config.PACKAGE_VERSION); - const gettextDomain = this.metadata['gettext-domain']; - - let UIFolderPath = this.dir.get_child('ui').get_path(); - let prefsKeys = new PrefsKeys(shellVersion); - - let prefs = new Prefs( - { - Builder: new Gtk.Builder(), - Settings: this.getSettings(), - Gdk, - }, - prefsKeys, - shellVersion - ); - - prefs.fillPrefsWindow(window, UIFolderPath, gettextDomain); - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/schemas/gschemas.compiled deleted file mode 100755 index ebb91030..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/schemas/org.gnome.shell.extensions.just-perfection.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/schemas/org.gnome.shell.extensions.just-perfection.gschema.xml deleted file mode 100755 index 8f761b2a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/schemas/org.gnome.shell.extensions.just-perfection.gschema.xml +++ /dev/null @@ -1,396 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<schemalist> - - <schema id="org.gnome.shell.extensions.just-perfection" - path="/org/gnome/shell/extensions/just-perfection/"> - - <key type="b" name="panel"> - <default>true</default> - <summary>Panel</summary> - <description>Panel Visibility Status</description> - </key> - - <key type="b" name="panel-in-overview"> - <default>false</default> - <summary>Panel in Overview</summary> - <description>Panel in Overview Visibility Status</description> - </key> - - <key type="b" name="background-menu"> - <default>true</default> - <summary>Background Menu</summary> - <description>Background Menu Status</description> - </key> - - <key type="b" name="search"> - <default>true</default> - <summary>Search Box</summary> - <description>Search Box Visibility Status</description> - </key> - - <key type="b" name="workspace"> - <default>true</default> - <summary>Workspace Switcher</summary> - <description>Workspace Switcher Visibility Status</description> - </key> - - <key type="b" name="dash"> - <default>true</default> - <summary>Dash</summary> - <description>Dash Visibility Status</description> - </key> - - <key type="b" name="osd"> - <default>true</default> - <summary>OSD</summary> - <description>OSD Visibility Status</description> - </key> - - <key type="b" name="workspace-popup"> - <default>true</default> - <summary>Workspace Popup</summary> - <description>Workspace Popup Visibility Status</description> - </key> - - <key type="b" name="theme"> - <default>false</default> - <summary>Theme</summary> - <description>Theme Status</description> - </key> - - <key type="b" name="activities-button"> - <default>true</default> - <summary>Activities Button</summary> - <description>Activities Button Visibility Status</description> - </key> - - <key type="b" name="clock-menu"> - <default>true</default> - <summary>Clock Menu</summary> - <description>Clock Menu Visibility Status</description> - </key> - - <key type="b" name="panel-notification-icon"> - <default>true</default> - <summary>Panel Notification Icon</summary> - <description>Panel Notification Icon Visibility Status</description> - </key> - - <key type="b" name="keyboard-layout"> - <default>true</default> - <summary>Keyboard Layout</summary> - <description>Keyboard Layout Visibility Status</description> - </key> - - <key type="b" name="accessibility-menu"> - <default>true</default> - <summary>Accessibility Menu</summary> - <description>Accessibility Menu Visibility Status</description> - </key> - - <key type="b" name="quick-settings"> - <default>true</default> - <summary>Quick Settings Menu</summary> - <description>Quick Settings Visibility Status</description> - </key> - - <key type="b" name="power-icon"> - <default>true</default> - <summary>Power Icon</summary> - <description>Power Icon Visibility Status</description> - </key> - - <key type="b" name="window-picker-icon"> - <default>true</default> - <summary>Window Picker Icon</summary> - <description>Window Picker Icon Visiblity</description> - </key> - - <key type="b" name="type-to-search"> - <default>true</default> - <summary>Type to Search</summary> - <description>Type to Search Behavior</description> - </key> - - <key type="i" name="panel-corner-size"> - <default>0</default> - <range min="0" max="61"/> - <summary>0 means use Shell theme, 1 means no border, 2 - 61 means border size</summary> - <description>Panel Corner Size</description> - </key> - - <key type="i" name="workspace-switcher-size"> - <default>0</default> - <range min="0" max="30"/> - <summary>Workspace Switcher Size in percent, 0 means use default size</summary> - <description>Workspace Switcher Size</description> - </key> - - <key type="i" name="top-panel-position"> - <default>0</default> - <range min="0" max="1"/> - <summary>Top Panel Position</summary> - <description>Top Panel Position Status</description> - </key> - - <key type="i" name="clock-menu-position"> - <default>0</default> - <range min="0" max="2"/> - <summary>0 means center, 1 means right, 2 means left</summary> - <description>Clock Menu Position Status</description> - </key> - - <key type="i" name="clock-menu-position-offset"> - <default>0</default> - <range min="0" max="20"/> - <summary>0 means start of the position</summary> - <description>Clock Menu Position Offset</description> - </key> - - <key type="b" name="show-apps-button"> - <default>true</default> - <summary>Show Apps Button Visiblity</summary> - <description>Show Apps Button Visiblity Status</description> - </key> - - <key type="i" name="animation"> - <default>1</default> - <range min="0" max="7"/> - <summary>0 means disabled, 1 means default speed, animation speed otherwise</summary> - <description>Animation Status</description> - </key> - - <key type="b" name="window-demands-attention-focus"> - <default>false</default> - <summary>Window Demands Attention Focus</summary> - <description>Window Demands Attention Focus Status</description> - </key> - - <key type="b" name="window-maximized-on-create"> - <default>false</default> - <summary>Window Maximized on Create</summary> - <description>Window Maximized on Create Status</description> - </key> - - <key type="i" name="dash-icon-size"> - <default>0</default> - <range min="0" max="64"/> - <summary>0 means default, 16, 22, 24, 32, 40, 48, 56, 64</summary> - <description>Dash Icon Size</description> - </key> - - <key type="i" name="startup-status"> - <default>1</default> - <range min="0" max="1"/> - <summary>0 means desktop, 1 means overview</summary> - <description>Startup Status</description> - </key> - - <key type="b" name="workspaces-in-app-grid"> - <default>true</default> - <summary>Workspaces Visiblity in App Grid</summary> - <description>Workspaces Visiblity in App Grid Status</description> - </key> - - <key type="i" name="notification-banner-position"> - <default>1</default> - <range min="0" max="5"/> - <summary>0: top start, 1: top center, 2: top end, 3: bottom start, 4: bottom center, 5: bottom end</summary> - <description>Notification Banner Position</description> - </key> - - <key type="b" name="workspace-switcher-should-show"> - <default>false</default> - <summary>Always Show Workspaces Switcher</summary> - <description>Always Show Workspace Switcher Status</description> - </key> - - <key type="i" name="panel-size"> - <default>0</default> - <range min="0" max="60"/> - <summary>0 means use Shell theme, 1 - 61 means size in pixels</summary> - <description>Panel Size</description> - </key> - - <key type="i" name="panel-button-padding-size"> - <default>0</default> - <range min="0" max="61"/> - <summary>0 means use Shell theme, 1 means no padding, 2 - 61 means padding size</summary> - <description>Panel Button Padding Size</description> - </key> - - <key type="i" name="panel-indicator-padding-size"> - <default>0</default> - <range min="0" max="61"/> - <summary>0 means use Shell theme, 1 means no padding, 2 - 61 means padding size</summary> - <description>Panel Indicator Padding Size</description> - </key> - - <key type="b" name="window-preview-caption"> - <default>true</default> - <summary>Window Preview Caption</summary> - <description>Window Preview Caption Status</description> - </key> - - <key type="b" name="window-preview-close-button"> - <default>true</default> - <summary>Window Preview Close Button</summary> - <description>Window Preview Close Button Status</description> - </key> - - <key type="i" name="workspace-background-corner-size"> - <default>0</default> - <range min="0" max="61"/> - <summary>0 means use default shell size, 1 means no radius, 2 - 61 means radius size</summary> - <description>Workspace Background Corner Size</description> - </key> - - <key type="b" name="workspace-wrap-around"> - <default>false</default> - <summary>Workspace Wrap Around</summary> - <description>Workspace Wrap Around Status</description> - </key> - - <key type="b" name="ripple-box"> - <default>true</default> - <summary>Ripple Box</summary> - <description>Ripple Box Status</description> - </key> - - <key type="b" name="double-super-to-appgrid"> - <default>true</default> - <summary>Double Supper To App Grid</summary> - <description>Double Supper To App Grid Status</description> - </key> - - <key type="b" name="overlay-key"> - <default>true</default> - <summary>Overlay Key</summary> - <description>Overlay Key to Overview Status</description> - </key> - - <key type="b" name="switcher-popup-delay"> - <default>true</default> - <summary>Switcher Popup Delay</summary> - <description>Removes the delay for all switcher popups like alt-tab, ctrl-alt-tab, keyboard layout, ...</description> - </key> - - <key type="b" name="world-clock"> - <default>true</default> - <summary>World Clock Visibility in Clock Menu</summary> - <description>World Clock Visibility Status</description> - </key> - - <key type="b" name="weather"> - <default>true</default> - <summary>Weather Visibility in Clock Menu</summary> - <description>Weather Visibility Status</description> - </key> - - <key type="b" name="events-button"> - <default>true</default> - <summary>Events Button Visibility in Clock Menu</summary> - <description>Events Button Visibility Status</description> - </key> - - <key type="b" name="calendar"> - <default>true</default> - <summary>Calendar Visibility in Clock Menu</summary> - <description>Calendar Visibility Status</description> - </key> - - <key type="i" name="panel-icon-size"> - <default>0</default> - <range min="0" max="60"/> - <summary>0 means use Shell theme, 1 - 60 means panel icon size</summary> - <description>Panel Icon Size</description> - </key> - - <key type="b" name="dash-separator"> - <default>true</default> - <summary>Dash Separator Visibility</summary> - <description>Dash Separator Visibility Status</description> - </key> - - <key type="b" name="workspace-peek"> - <default>true</default> - <summary>Workspace Peek</summary> - <description>Workspace Peek Status</description> - </key> - - <key type="i" name="looking-glass-width"> - <default>0</default> - <range min="0" max="9"/> - <summary>Width Size in percent, 0 means use default size</summary> - <description>Looking Glass Width size</description> - </key> - - <key type="i" name="looking-glass-height"> - <default>0</default> - <range min="0" max="9"/> - <summary>Height Size in percent, 0 means use default size</summary> - <description>Looking Glass Height size</description> - </key> - - <key type="i" name="osd-position"> - <default>0</default> - <range min="0" max="9"/> - <summary>OSD Position</summary> - <description>OSD Position Status</description> - </key> - - <key type="b" name="window-menu-take-screenshot-button"> - <default>true</default> - <summary>Window Menu Take Screenshot Button Visibility</summary> - <description>Window Menu Take Screenshot Button Visibility Status</description> - </key> - - <key type="i" name="alt-tab-window-preview-size"> - <default>0</default> - <range min="0" max="512"/> - <summary>0 means default size</summary> - <description>Alt Tab Window Preview Size</description> - </key> - - <key type="i" name="alt-tab-small-icon-size"> - <default>0</default> - <range min="0" max="512"/> - <summary>0 means default size</summary> - <description>Alt Tab Small Icon Size (Window Preview Icon Size)</description> - </key> - - <key type="i" name="alt-tab-icon-size"> - <default>0</default> - <range min="0" max="512"/> - <summary>0 means default size</summary> - <description>Alt Tab Icon Size</description> - </key> - - <key type="b" name="screen-sharing-indicator"> - <default>true</default> - <summary>Screen Sharing Indicator Visibility in Panel</summary> - <description>Screen Sharing Indicator Visibility Status</description> - </key> - - <key type="b" name="screen-recording-indicator"> - <default>true</default> - <summary>Screen Recording Indicator Visibility in Panel</summary> - <description>Screen Recording Indicator Visibility Status</description> - </key> - - <key type="i" name="controls-manager-spacing-size"> - <default>0</default> - <range min="0" max="150"/> - <summary>0 means default size</summary> - <description>Controls manager spacing Size (overview spacing)</description> - </key> - - <key type="b" name="dash-app-running"> - <default>true</default> - <summary>Dash app running dot</summary> - <description>Dash app running dot visibility status</description> - </key> - - </schema> - -</schemalist> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/stylesheet.css deleted file mode 100755 index 3de52528..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/stylesheet.css +++ /dev/null @@ -1,713 +0,0 @@ -.just-perfection -{ - font-size: small; -} - -.just-perfection .switcher-popup -{ - padding: 8px; - spacing: 24px; - font-size: small; -} - -.just-perfection .switcher-list -{ - color: #eeeeec; - background-color: rgba(0, 0, 0, .99); - border: 0 solid rgba(255, 255, 255, .16); - border-radius: 15px; - padding: 12px; - box-shadow: none; -} - -.just-perfection .switcher-list .item-box -{ - padding: 8px; - border-radius: 14px; - border: 1px solid transparent; -} - -.just-perfection .switcher-list .item-box:outlined -{ - border: 0; - background-color: rgba(255, 255, 255, .1); - box-shadow: inset 0 2px 2px 0 rgba(0, 0, 0, .4); -} - -.just-perfection .switcher-list .item-box:selected -{ - background-color: #404040; - color: #eeeeec; -} - -.just-perfection .switcher-list .thumbnail-box -{ - padding: 2px; - spacing: 6px; -} - -.just-perfection .switcher-list .thumbnail -{ - width: 256px; -} - -.just-perfection .switcher-list .separator -{ - width: 1px; - background: #272727; -} - -.just-perfection .switcher-list .switcher-list-item-container -{ - spacing: 12px; -} - -.just-perfection .workspace-switcher-container -{ - background-color: rgba(0, 0, 0, .7); - box-shadow: none; - padding: 3px; - border: 0; - border-radius: 3px; -} - -.just-perfection .workspace-switcher -{ - background: transparent; - border: none; - border-radius: 0; - padding: 0; - spacing: 4px; -} - -.just-perfection .workspace-switcher -{ - background: rgba(0, 0, 0, .7); - box-shadow: none; - border: none; - border-radius: 5px; - padding: 0; - spacing: 4px; -} - -.just-perfection .ws-switcher-indicator, -.just-perfection .ws-switcher-indicator:active -{ - background: transparent; - background-color: rgba(255, 255, 255, .02); - height: 8px; - width: 20px; - border: 0; - border-radius: 2px; - padding: 2px; - margin: 5px; -} - -.just-perfection .ws-switcher-indicator:active -{ - background-color: rgba(255, 255, 255, .8); -} - -.just-perfection .ws-switcher-box -{ - background: transparent; - background-color: rgba(255, 255, 255, .02); - height: 10px; - background-size: 0; - border: 0; - border-radius: 1px; -} - -.just-perfection .ws-switcher-active-up, -.just-perfection .ws-switcher-active-down, -.just-perfection .ws-switcher-active-left, -.just-perfection .ws-switcher-active-right -{ - height: 10px; - background-color: rgba(255, 255, 255, .8); - border: 0; - border-radius: 1px; -} - -.just-perfection .osd-window -{ - background-color: rgba(0, 0, 0, 1); - border: 0; - border-radius: 8px; - padding: 10px; - box-shadow: none; -} - -.just-perfection .osd-window StIcon -{ - width: 22px; - height: 22px; -} - -.just-perfection .tile-preview -{ - background-color: rgba(255, 255, 255, 0.15); - border: 1px solid rgba(255, 255, 255, 0.6); - border-radius: 0; -} - -.just-perfection-api-no-search #overview -{ - spacing: 0; -} - -.just-perfection-api-no-search .overview-controls -{ - padding-top: 36px; - padding-bottom: 36px; -} - -/* commented because the icon will be shown when the window is getting dragged */ -/* icon-dropshadow isn't specific to the window picker icon but that's a quick fix for now */ -/* .just-perfection-api-no-window-picker-icon .workspaces-view StIcon */ -.just-perfection-api-no-window-picker-icon .icon-dropshadow -{ - width: 0; - height: 0; - padding: 0; -} - -.just-perfection-api-bottom-panel #overview -{ - margin-bottom: 24px; -} - -.just-perfection-api-bottom-panel .popup-menu.panel-menu -{ - margin-bottom: 0; -} - -.just-perfection-api-bottom-panel.just-perfection-api-no-panel #overview -{ - margin-bottom: 0; -} - -.just-perfection-api-no-panel #panel -{ - background-color: transparent; -} - -.just-perfection-api-no-panel-arrow .panel-button .popup-menu-arrow -{ - width: 0; - height: 0; -} - -.just-perfection-api-no-panel-notification-icon .clock-display StIcon -{ - width: 0; - height: 0; - padding: 0; -} - -.just-perfection-api-no-panel-notification-icon .clock-display-box -{ - padding: 0; - spacing: 0; -} - -.just-perfection-api-no-show-apps-button .show-apps, -.just-perfection-api-no-show-apps-button .show-apps StIcon -{ - width: 0; - margin: 0; - spacing: 0; -} - -.just-perfection-api-dash-icon-size16 #dash StIcon { height: 16px; width: 16px; } -.just-perfection-api-dash-icon-size22 #dash StIcon { height: 22px; width: 22px; } -.just-perfection-api-dash-icon-size24 #dash StIcon { height: 24px; width: 24px; } -.just-perfection-api-dash-icon-size32 #dash StIcon { height: 32px; width: 32px; } -.just-perfection-api-dash-icon-size40 #dash StIcon { height: 40px; width: 40px; } -.just-perfection-api-dash-icon-size48 #dash StIcon { height: 48px; width: 48px; } -.just-perfection-api-dash-icon-size56 #dash StIcon { height: 56px; width: 56px; } -.just-perfection-api-dash-icon-size64 #dash StIcon { height: 64px; width: 64px; } - - -.just-perfection-api-panel-button-padding-size0 .panel-button { -natural-hpadding: 0px; -minimum-hpadding: 0px; } -.just-perfection-api-panel-button-padding-size1 .panel-button { -natural-hpadding: 1px; -minimum-hpadding: 1px; } -.just-perfection-api-panel-button-padding-size2 .panel-button { -natural-hpadding: 2px; -minimum-hpadding: 2px; } -.just-perfection-api-panel-button-padding-size3 .panel-button { -natural-hpadding: 3px; -minimum-hpadding: 3px; } -.just-perfection-api-panel-button-padding-size4 .panel-button { -natural-hpadding: 4px; -minimum-hpadding: 4px; } -.just-perfection-api-panel-button-padding-size5 .panel-button { -natural-hpadding: 5px; -minimum-hpadding: 5px; } -.just-perfection-api-panel-button-padding-size6 .panel-button { -natural-hpadding: 6px; -minimum-hpadding: 6px; } -.just-perfection-api-panel-button-padding-size7 .panel-button { -natural-hpadding: 7px; -minimum-hpadding: 7px; } -.just-perfection-api-panel-button-padding-size8 .panel-button { -natural-hpadding: 8px; -minimum-hpadding: 8px; } -.just-perfection-api-panel-button-padding-size9 .panel-button { -natural-hpadding: 9px; -minimum-hpadding: 9px; } -.just-perfection-api-panel-button-padding-size10 .panel-button { -natural-hpadding: 10px; -minimum-hpadding: 10px; } -.just-perfection-api-panel-button-padding-size11 .panel-button { -natural-hpadding: 11px; -minimum-hpadding: 11px; } -.just-perfection-api-panel-button-padding-size12 .panel-button { -natural-hpadding: 12px; -minimum-hpadding: 12px; } -.just-perfection-api-panel-button-padding-size13 .panel-button { -natural-hpadding: 13px; -minimum-hpadding: 13px; } -.just-perfection-api-panel-button-padding-size14 .panel-button { -natural-hpadding: 14px; -minimum-hpadding: 14px; } -.just-perfection-api-panel-button-padding-size15 .panel-button { -natural-hpadding: 15px; -minimum-hpadding: 15px; } -.just-perfection-api-panel-button-padding-size16 .panel-button { -natural-hpadding: 16px; -minimum-hpadding: 16px; } -.just-perfection-api-panel-button-padding-size17 .panel-button { -natural-hpadding: 17px; -minimum-hpadding: 17px; } -.just-perfection-api-panel-button-padding-size18 .panel-button { -natural-hpadding: 18px; -minimum-hpadding: 18px; } -.just-perfection-api-panel-button-padding-size19 .panel-button { -natural-hpadding: 19px; -minimum-hpadding: 19px; } -.just-perfection-api-panel-button-padding-size20 .panel-button { -natural-hpadding: 20px; -minimum-hpadding: 20px; } -.just-perfection-api-panel-button-padding-size21 .panel-button { -natural-hpadding: 21px; -minimum-hpadding: 21px; } -.just-perfection-api-panel-button-padding-size22 .panel-button { -natural-hpadding: 22px; -minimum-hpadding: 22px; } -.just-perfection-api-panel-button-padding-size23 .panel-button { -natural-hpadding: 23px; -minimum-hpadding: 23px; } -.just-perfection-api-panel-button-padding-size24 .panel-button { -natural-hpadding: 24px; -minimum-hpadding: 24px; } -.just-perfection-api-panel-button-padding-size25 .panel-button { -natural-hpadding: 25px; -minimum-hpadding: 25px; } -.just-perfection-api-panel-button-padding-size26 .panel-button { -natural-hpadding: 26px; -minimum-hpadding: 26px; } -.just-perfection-api-panel-button-padding-size27 .panel-button { -natural-hpadding: 27px; -minimum-hpadding: 27px; } -.just-perfection-api-panel-button-padding-size28 .panel-button { -natural-hpadding: 28px; -minimum-hpadding: 28px; } -.just-perfection-api-panel-button-padding-size29 .panel-button { -natural-hpadding: 29px; -minimum-hpadding: 29px; } -.just-perfection-api-panel-button-padding-size30 .panel-button { -natural-hpadding: 30px; -minimum-hpadding: 30px; } -.just-perfection-api-panel-button-padding-size31 .panel-button { -natural-hpadding: 31px; -minimum-hpadding: 31px; } -.just-perfection-api-panel-button-padding-size32 .panel-button { -natural-hpadding: 32px; -minimum-hpadding: 32px; } -.just-perfection-api-panel-button-padding-size33 .panel-button { -natural-hpadding: 33px; -minimum-hpadding: 33px; } -.just-perfection-api-panel-button-padding-size34 .panel-button { -natural-hpadding: 34px; -minimum-hpadding: 34px; } -.just-perfection-api-panel-button-padding-size35 .panel-button { -natural-hpadding: 35px; -minimum-hpadding: 35px; } -.just-perfection-api-panel-button-padding-size36 .panel-button { -natural-hpadding: 36px; -minimum-hpadding: 36px; } -.just-perfection-api-panel-button-padding-size37 .panel-button { -natural-hpadding: 37px; -minimum-hpadding: 37px; } -.just-perfection-api-panel-button-padding-size38 .panel-button { -natural-hpadding: 38px; -minimum-hpadding: 38px; } -.just-perfection-api-panel-button-padding-size39 .panel-button { -natural-hpadding: 39px; -minimum-hpadding: 39px; } -.just-perfection-api-panel-button-padding-size40 .panel-button { -natural-hpadding: 40px; -minimum-hpadding: 40px; } -.just-perfection-api-panel-button-padding-size41 .panel-button { -natural-hpadding: 41px; -minimum-hpadding: 41px; } -.just-perfection-api-panel-button-padding-size42 .panel-button { -natural-hpadding: 42px; -minimum-hpadding: 42px; } -.just-perfection-api-panel-button-padding-size43 .panel-button { -natural-hpadding: 43px; -minimum-hpadding: 43px; } -.just-perfection-api-panel-button-padding-size44 .panel-button { -natural-hpadding: 44px; -minimum-hpadding: 44px; } -.just-perfection-api-panel-button-padding-size45 .panel-button { -natural-hpadding: 45px; -minimum-hpadding: 45px; } -.just-perfection-api-panel-button-padding-size46 .panel-button { -natural-hpadding: 46px; -minimum-hpadding: 46px; } -.just-perfection-api-panel-button-padding-size47 .panel-button { -natural-hpadding: 47px; -minimum-hpadding: 47px; } -.just-perfection-api-panel-button-padding-size48 .panel-button { -natural-hpadding: 48px; -minimum-hpadding: 48px; } -.just-perfection-api-panel-button-padding-size49 .panel-button { -natural-hpadding: 49px; -minimum-hpadding: 49px; } -.just-perfection-api-panel-button-padding-size50 .panel-button { -natural-hpadding: 50px; -minimum-hpadding: 50px; } -.just-perfection-api-panel-button-padding-size51 .panel-button { -natural-hpadding: 51px; -minimum-hpadding: 51px; } -.just-perfection-api-panel-button-padding-size52 .panel-button { -natural-hpadding: 52px; -minimum-hpadding: 52px; } -.just-perfection-api-panel-button-padding-size53 .panel-button { -natural-hpadding: 53px; -minimum-hpadding: 53px; } -.just-perfection-api-panel-button-padding-size54 .panel-button { -natural-hpadding: 54px; -minimum-hpadding: 54px; } -.just-perfection-api-panel-button-padding-size55 .panel-button { -natural-hpadding: 55px; -minimum-hpadding: 55px; } -.just-perfection-api-panel-button-padding-size56 .panel-button { -natural-hpadding: 56px; -minimum-hpadding: 56px; } -.just-perfection-api-panel-button-padding-size57 .panel-button { -natural-hpadding: 57px; -minimum-hpadding: 57px; } -.just-perfection-api-panel-button-padding-size58 .panel-button { -natural-hpadding: 58px; -minimum-hpadding: 58px; } -.just-perfection-api-panel-button-padding-size59 .panel-button { -natural-hpadding: 59px; -minimum-hpadding: 59px; } -.just-perfection-api-panel-button-padding-size60 .panel-button { -natural-hpadding: 60px; -minimum-hpadding: 60px; } - -.just-perfection-api-no-window-caption .window-caption -{ - spacing: 0; - background-color: transparent; - border-radius: 0; - border: 0; - padding: 0; - font-size: 0; -} - -.just-perfection-api-workspace-background-radius-size0 .workspace-background { border-radius: 0; } -.just-perfection-api-workspace-background-radius-size1 .workspace-background { border-radius: 1px; } -.just-perfection-api-workspace-background-radius-size2 .workspace-background { border-radius: 2px; } -.just-perfection-api-workspace-background-radius-size3 .workspace-background { border-radius: 3px; } -.just-perfection-api-workspace-background-radius-size4 .workspace-background { border-radius: 4px; } -.just-perfection-api-workspace-background-radius-size5 .workspace-background { border-radius: 5px; } -.just-perfection-api-workspace-background-radius-size6 .workspace-background { border-radius: 6px; } -.just-perfection-api-workspace-background-radius-size7 .workspace-background { border-radius: 7px; } -.just-perfection-api-workspace-background-radius-size8 .workspace-background { border-radius: 8px; } -.just-perfection-api-workspace-background-radius-size9 .workspace-background { border-radius: 9px; } -.just-perfection-api-workspace-background-radius-size10 .workspace-background { border-radius: 10px; } -.just-perfection-api-workspace-background-radius-size11 .workspace-background { border-radius: 11px; } -.just-perfection-api-workspace-background-radius-size12 .workspace-background { border-radius: 12px; } -.just-perfection-api-workspace-background-radius-size13 .workspace-background { border-radius: 13px; } -.just-perfection-api-workspace-background-radius-size14 .workspace-background { border-radius: 14px; } -.just-perfection-api-workspace-background-radius-size15 .workspace-background { border-radius: 15px; } -.just-perfection-api-workspace-background-radius-size16 .workspace-background { border-radius: 16px; } -.just-perfection-api-workspace-background-radius-size17 .workspace-background { border-radius: 17px; } -.just-perfection-api-workspace-background-radius-size18 .workspace-background { border-radius: 18px; } -.just-perfection-api-workspace-background-radius-size19 .workspace-background { border-radius: 19px; } -.just-perfection-api-workspace-background-radius-size20 .workspace-background { border-radius: 20px; } -.just-perfection-api-workspace-background-radius-size21 .workspace-background { border-radius: 21px; } -.just-perfection-api-workspace-background-radius-size22 .workspace-background { border-radius: 22px; } -.just-perfection-api-workspace-background-radius-size23 .workspace-background { border-radius: 23px; } -.just-perfection-api-workspace-background-radius-size24 .workspace-background { border-radius: 24px; } -.just-perfection-api-workspace-background-radius-size25 .workspace-background { border-radius: 25px; } -.just-perfection-api-workspace-background-radius-size26 .workspace-background { border-radius: 26px; } -.just-perfection-api-workspace-background-radius-size27 .workspace-background { border-radius: 27px; } -.just-perfection-api-workspace-background-radius-size28 .workspace-background { border-radius: 28px; } -.just-perfection-api-workspace-background-radius-size29 .workspace-background { border-radius: 29px; } -.just-perfection-api-workspace-background-radius-size30 .workspace-background { border-radius: 30px; } -.just-perfection-api-workspace-background-radius-size31 .workspace-background { border-radius: 31px; } -.just-perfection-api-workspace-background-radius-size32 .workspace-background { border-radius: 32px; } -.just-perfection-api-workspace-background-radius-size33 .workspace-background { border-radius: 33px; } -.just-perfection-api-workspace-background-radius-size34 .workspace-background { border-radius: 34px; } -.just-perfection-api-workspace-background-radius-size35 .workspace-background { border-radius: 35px; } -.just-perfection-api-workspace-background-radius-size36 .workspace-background { border-radius: 36px; } -.just-perfection-api-workspace-background-radius-size37 .workspace-background { border-radius: 37px; } -.just-perfection-api-workspace-background-radius-size38 .workspace-background { border-radius: 38px; } -.just-perfection-api-workspace-background-radius-size39 .workspace-background { border-radius: 39px; } -.just-perfection-api-workspace-background-radius-size40 .workspace-background { border-radius: 40px; } -.just-perfection-api-workspace-background-radius-size41 .workspace-background { border-radius: 41px; } -.just-perfection-api-workspace-background-radius-size42 .workspace-background { border-radius: 42px; } -.just-perfection-api-workspace-background-radius-size43 .workspace-background { border-radius: 43px; } -.just-perfection-api-workspace-background-radius-size44 .workspace-background { border-radius: 44px; } -.just-perfection-api-workspace-background-radius-size45 .workspace-background { border-radius: 45px; } -.just-perfection-api-workspace-background-radius-size46 .workspace-background { border-radius: 46px; } -.just-perfection-api-workspace-background-radius-size47 .workspace-background { border-radius: 47px; } -.just-perfection-api-workspace-background-radius-size48 .workspace-background { border-radius: 48px; } -.just-perfection-api-workspace-background-radius-size49 .workspace-background { border-radius: 49px; } -.just-perfection-api-workspace-background-radius-size50 .workspace-background { border-radius: 50px; } -.just-perfection-api-workspace-background-radius-size51 .workspace-background { border-radius: 51px; } -.just-perfection-api-workspace-background-radius-size52 .workspace-background { border-radius: 52px; } -.just-perfection-api-workspace-background-radius-size53 .workspace-background { border-radius: 53px; } -.just-perfection-api-workspace-background-radius-size54 .workspace-background { border-radius: 54px; } -.just-perfection-api-workspace-background-radius-size55 .workspace-background { border-radius: 55px; } -.just-perfection-api-workspace-background-radius-size56 .workspace-background { border-radius: 56px; } -.just-perfection-api-workspace-background-radius-size57 .workspace-background { border-radius: 57px; } -.just-perfection-api-workspace-background-radius-size58 .workspace-background { border-radius: 58px; } -.just-perfection-api-workspace-background-radius-size59 .workspace-background { border-radius: 59px; } -.just-perfection-api-workspace-background-radius-size60 .workspace-background { border-radius: 60px; } - -.just-perfection-api-panel-indicator-padding-size0 .panel-status-indicators-box { spacing: 0; } -.just-perfection-api-panel-indicator-padding-size1 .panel-status-indicators-box { spacing: 1px; } -.just-perfection-api-panel-indicator-padding-size2 .panel-status-indicators-box { spacing: 2px; } -.just-perfection-api-panel-indicator-padding-size3 .panel-status-indicators-box { spacing: 3px; } -.just-perfection-api-panel-indicator-padding-size4 .panel-status-indicators-box { spacing: 4px; } -.just-perfection-api-panel-indicator-padding-size5 .panel-status-indicators-box { spacing: 5px; } -.just-perfection-api-panel-indicator-padding-size6 .panel-status-indicators-box { spacing: 6px; } -.just-perfection-api-panel-indicator-padding-size7 .panel-status-indicators-box { spacing: 7px; } -.just-perfection-api-panel-indicator-padding-size8 .panel-status-indicators-box { spacing: 8px; } -.just-perfection-api-panel-indicator-padding-size9 .panel-status-indicators-box { spacing: 9px; } -.just-perfection-api-panel-indicator-padding-size10 .panel-status-indicators-box { spacing: 10px; } -.just-perfection-api-panel-indicator-padding-size11 .panel-status-indicators-box { spacing: 11px; } -.just-perfection-api-panel-indicator-padding-size12 .panel-status-indicators-box { spacing: 12px; } -.just-perfection-api-panel-indicator-padding-size13 .panel-status-indicators-box { spacing: 13px; } -.just-perfection-api-panel-indicator-padding-size14 .panel-status-indicators-box { spacing: 14px; } -.just-perfection-api-panel-indicator-padding-size15 .panel-status-indicators-box { spacing: 15px; } -.just-perfection-api-panel-indicator-padding-size16 .panel-status-indicators-box { spacing: 16px; } -.just-perfection-api-panel-indicator-padding-size17 .panel-status-indicators-box { spacing: 17px; } -.just-perfection-api-panel-indicator-padding-size18 .panel-status-indicators-box { spacing: 18px; } -.just-perfection-api-panel-indicator-padding-size19 .panel-status-indicators-box { spacing: 19px; } -.just-perfection-api-panel-indicator-padding-size20 .panel-status-indicators-box { spacing: 20px; } -.just-perfection-api-panel-indicator-padding-size21 .panel-status-indicators-box { spacing: 21px; } -.just-perfection-api-panel-indicator-padding-size22 .panel-status-indicators-box { spacing: 22px; } -.just-perfection-api-panel-indicator-padding-size23 .panel-status-indicators-box { spacing: 23px; } -.just-perfection-api-panel-indicator-padding-size24 .panel-status-indicators-box { spacing: 24px; } -.just-perfection-api-panel-indicator-padding-size25 .panel-status-indicators-box { spacing: 25px; } -.just-perfection-api-panel-indicator-padding-size26 .panel-status-indicators-box { spacing: 26px; } -.just-perfection-api-panel-indicator-padding-size27 .panel-status-indicators-box { spacing: 27px; } -.just-perfection-api-panel-indicator-padding-size28 .panel-status-indicators-box { spacing: 28px; } -.just-perfection-api-panel-indicator-padding-size29 .panel-status-indicators-box { spacing: 29px; } -.just-perfection-api-panel-indicator-padding-size30 .panel-status-indicators-box { spacing: 30px; } -.just-perfection-api-panel-indicator-padding-size31 .panel-status-indicators-box { spacing: 31px; } -.just-perfection-api-panel-indicator-padding-size32 .panel-status-indicators-box { spacing: 32px; } -.just-perfection-api-panel-indicator-padding-size33 .panel-status-indicators-box { spacing: 33px; } -.just-perfection-api-panel-indicator-padding-size34 .panel-status-indicators-box { spacing: 34px; } -.just-perfection-api-panel-indicator-padding-size35 .panel-status-indicators-box { spacing: 35px; } -.just-perfection-api-panel-indicator-padding-size36 .panel-status-indicators-box { spacing: 36px; } -.just-perfection-api-panel-indicator-padding-size37 .panel-status-indicators-box { spacing: 37px; } -.just-perfection-api-panel-indicator-padding-size38 .panel-status-indicators-box { spacing: 38px; } -.just-perfection-api-panel-indicator-padding-size39 .panel-status-indicators-box { spacing: 39px; } -.just-perfection-api-panel-indicator-padding-size40 .panel-status-indicators-box { spacing: 40px; } -.just-perfection-api-panel-indicator-padding-size41 .panel-status-indicators-box { spacing: 41px; } -.just-perfection-api-panel-indicator-padding-size42 .panel-status-indicators-box { spacing: 42px; } -.just-perfection-api-panel-indicator-padding-size43 .panel-status-indicators-box { spacing: 43px; } -.just-perfection-api-panel-indicator-padding-size44 .panel-status-indicators-box { spacing: 44px; } -.just-perfection-api-panel-indicator-padding-size45 .panel-status-indicators-box { spacing: 45px; } -.just-perfection-api-panel-indicator-padding-size46 .panel-status-indicators-box { spacing: 46px; } -.just-perfection-api-panel-indicator-padding-size47 .panel-status-indicators-box { spacing: 47px; } -.just-perfection-api-panel-indicator-padding-size48 .panel-status-indicators-box { spacing: 48px; } -.just-perfection-api-panel-indicator-padding-size49 .panel-status-indicators-box { spacing: 49px; } -.just-perfection-api-panel-indicator-padding-size50 .panel-status-indicators-box { spacing: 50px; } -.just-perfection-api-panel-indicator-padding-size51 .panel-status-indicators-box { spacing: 51px; } -.just-perfection-api-panel-indicator-padding-size52 .panel-status-indicators-box { spacing: 52px; } -.just-perfection-api-panel-indicator-padding-size53 .panel-status-indicators-box { spacing: 53px; } -.just-perfection-api-panel-indicator-padding-size54 .panel-status-indicators-box { spacing: 54px; } -.just-perfection-api-panel-indicator-padding-size55 .panel-status-indicators-box { spacing: 55px; } -.just-perfection-api-panel-indicator-padding-size56 .panel-status-indicators-box { spacing: 56px; } -.just-perfection-api-panel-indicator-padding-size57 .panel-status-indicators-box { spacing: 57px; } -.just-perfection-api-panel-indicator-padding-size58 .panel-status-indicators-box { spacing: 58px; } -.just-perfection-api-panel-indicator-padding-size59 .panel-status-indicators-box { spacing: 59px; } -.just-perfection-api-panel-indicator-padding-size60 .panel-status-indicators-box { spacing: 60px; } - -.just-perfection-api-no-window-close .window-close, -.just-perfection-api-no-window-close.just-perfection .window-close -{ - height: 0; - width: 30px; - background: transparent; - border-radius: 0; - border: 0; - spacing: 0; - box-shadow: none; -} - -.just-perfection-api-no-ripple-box .ripple-box -{ - background-color: transparent; -} - -/** - * This can refresh other styles that is not inculding any standard css styles. - * values are not important here. Just do something that can change the look - */ -.just-perfection-api-refresh-styles .panel-button, -.just-perfection-api-refresh-styles .panel-status-indicators-box, -.just-perfection-api-refresh-styles .panel-button StIcon, -.just-perfection-api-refresh-styles .system-status-icon -{ - background-color: gold; - color: gold; - border-radius: 100px; -} - -.just-perfection-api-no-weather .weather-button, -.just-perfection-api-no-weather .weather-button *, -.just-perfection-api-no-events-button .events-button, -.just-perfection-api-no-events-button .events-button *, -.just-perfection-api-no-screen-sharing-indicator .screen-sharing-indicator, -.just-perfection-api-no-screen-sharing-indicator .screen-sharing-indicator *, -.just-perfection-api-no-screen-recording-indicator .screen-recording-indicator, -.just-perfection-api-no-screen-recording-indicator .screen-recording-indicator * -{ - padding: 0; - margin: 0; - border: 0; - height: 0; - width: 0; -} - -.just-perfection-api-panel-icon-size1 .system-status-icon, .just-perfection-api-panel-icon-size1 .panel-button StIcon { icon-size: 1px; } -.just-perfection-api-panel-icon-size2 .system-status-icon, .just-perfection-api-panel-icon-size2 .panel-button StIcon { icon-size: 2px; } -.just-perfection-api-panel-icon-size3 .system-status-icon, .just-perfection-api-panel-icon-size3 .panel-button StIcon { icon-size: 3px; } -.just-perfection-api-panel-icon-size4 .system-status-icon, .just-perfection-api-panel-icon-size4 .panel-button StIcon { icon-size: 4px; } -.just-perfection-api-panel-icon-size5 .system-status-icon, .just-perfection-api-panel-icon-size5 .panel-button StIcon { icon-size: 5px; } -.just-perfection-api-panel-icon-size6 .system-status-icon, .just-perfection-api-panel-icon-size6 .panel-button StIcon { icon-size: 6px; } -.just-perfection-api-panel-icon-size7 .system-status-icon, .just-perfection-api-panel-icon-size7 .panel-button StIcon { icon-size: 7px; } -.just-perfection-api-panel-icon-size8 .system-status-icon, .just-perfection-api-panel-icon-size8 .panel-button StIcon { icon-size: 8px; } -.just-perfection-api-panel-icon-size9 .system-status-icon, .just-perfection-api-panel-icon-size9 .panel-button StIcon { icon-size: 9px; } -.just-perfection-api-panel-icon-size10 .system-status-icon, .just-perfection-api-panel-icon-size10 .panel-button StIcon { icon-size: 10px; } -.just-perfection-api-panel-icon-size11 .system-status-icon, .just-perfection-api-panel-icon-size11 .panel-button StIcon { icon-size: 11px; } -.just-perfection-api-panel-icon-size12 .system-status-icon, .just-perfection-api-panel-icon-size12 .panel-button StIcon { icon-size: 12px; } -.just-perfection-api-panel-icon-size13 .system-status-icon, .just-perfection-api-panel-icon-size13 .panel-button StIcon { icon-size: 13px; } -.just-perfection-api-panel-icon-size14 .system-status-icon, .just-perfection-api-panel-icon-size14 .panel-button StIcon { icon-size: 14px; } -.just-perfection-api-panel-icon-size15 .system-status-icon, .just-perfection-api-panel-icon-size15 .panel-button StIcon { icon-size: 15px; } -.just-perfection-api-panel-icon-size16 .system-status-icon, .just-perfection-api-panel-icon-size16 .panel-button StIcon { icon-size: 16px; } -.just-perfection-api-panel-icon-size17 .system-status-icon, .just-perfection-api-panel-icon-size17 .panel-button StIcon { icon-size: 17px; } -.just-perfection-api-panel-icon-size18 .system-status-icon, .just-perfection-api-panel-icon-size18 .panel-button StIcon { icon-size: 18px; } -.just-perfection-api-panel-icon-size19 .system-status-icon, .just-perfection-api-panel-icon-size19 .panel-button StIcon { icon-size: 19px; } -.just-perfection-api-panel-icon-size20 .system-status-icon, .just-perfection-api-panel-icon-size20 .panel-button StIcon { icon-size: 20px; } -.just-perfection-api-panel-icon-size21 .system-status-icon, .just-perfection-api-panel-icon-size21 .panel-button StIcon { icon-size: 21px; } -.just-perfection-api-panel-icon-size22 .system-status-icon, .just-perfection-api-panel-icon-size22 .panel-button StIcon { icon-size: 22px; } -.just-perfection-api-panel-icon-size23 .system-status-icon, .just-perfection-api-panel-icon-size23 .panel-button StIcon { icon-size: 23px; } -.just-perfection-api-panel-icon-size24 .system-status-icon, .just-perfection-api-panel-icon-size24 .panel-button StIcon { icon-size: 24px; } -.just-perfection-api-panel-icon-size25 .system-status-icon, .just-perfection-api-panel-icon-size25 .panel-button StIcon { icon-size: 25px; } -.just-perfection-api-panel-icon-size26 .system-status-icon, .just-perfection-api-panel-icon-size26 .panel-button StIcon { icon-size: 26px; } -.just-perfection-api-panel-icon-size27 .system-status-icon, .just-perfection-api-panel-icon-size27 .panel-button StIcon { icon-size: 27px; } -.just-perfection-api-panel-icon-size28 .system-status-icon, .just-perfection-api-panel-icon-size28 .panel-button StIcon { icon-size: 28px; } -.just-perfection-api-panel-icon-size29 .system-status-icon, .just-perfection-api-panel-icon-size29 .panel-button StIcon { icon-size: 29px; } -.just-perfection-api-panel-icon-size30 .system-status-icon, .just-perfection-api-panel-icon-size30 .panel-button StIcon { icon-size: 30px; } -.just-perfection-api-panel-icon-size31 .system-status-icon, .just-perfection-api-panel-icon-size31 .panel-button StIcon { icon-size: 31px; } -.just-perfection-api-panel-icon-size32 .system-status-icon, .just-perfection-api-panel-icon-size32 .panel-button StIcon { icon-size: 32px; } -.just-perfection-api-panel-icon-size33 .system-status-icon, .just-perfection-api-panel-icon-size33 .panel-button StIcon { icon-size: 33px; } -.just-perfection-api-panel-icon-size34 .system-status-icon, .just-perfection-api-panel-icon-size34 .panel-button StIcon { icon-size: 34px; } -.just-perfection-api-panel-icon-size35 .system-status-icon, .just-perfection-api-panel-icon-size35 .panel-button StIcon { icon-size: 35px; } -.just-perfection-api-panel-icon-size36 .system-status-icon, .just-perfection-api-panel-icon-size36 .panel-button StIcon { icon-size: 36px; } -.just-perfection-api-panel-icon-size37 .system-status-icon, .just-perfection-api-panel-icon-size37 .panel-button StIcon { icon-size: 37px; } -.just-perfection-api-panel-icon-size38 .system-status-icon, .just-perfection-api-panel-icon-size38 .panel-button StIcon { icon-size: 38px; } -.just-perfection-api-panel-icon-size39 .system-status-icon, .just-perfection-api-panel-icon-size39 .panel-button StIcon { icon-size: 39px; } -.just-perfection-api-panel-icon-size40 .system-status-icon, .just-perfection-api-panel-icon-size40 .panel-button StIcon { icon-size: 40px; } -.just-perfection-api-panel-icon-size41 .system-status-icon, .just-perfection-api-panel-icon-size41 .panel-button StIcon { icon-size: 41px; } -.just-perfection-api-panel-icon-size42 .system-status-icon, .just-perfection-api-panel-icon-size42 .panel-button StIcon { icon-size: 42px; } -.just-perfection-api-panel-icon-size43 .system-status-icon, .just-perfection-api-panel-icon-size43 .panel-button StIcon { icon-size: 43px; } -.just-perfection-api-panel-icon-size44 .system-status-icon, .just-perfection-api-panel-icon-size44 .panel-button StIcon { icon-size: 44px; } -.just-perfection-api-panel-icon-size45 .system-status-icon, .just-perfection-api-panel-icon-size45 .panel-button StIcon { icon-size: 45px; } -.just-perfection-api-panel-icon-size46 .system-status-icon, .just-perfection-api-panel-icon-size46 .panel-button StIcon { icon-size: 46px; } -.just-perfection-api-panel-icon-size47 .system-status-icon, .just-perfection-api-panel-icon-size47 .panel-button StIcon { icon-size: 47px; } -.just-perfection-api-panel-icon-size48 .system-status-icon, .just-perfection-api-panel-icon-size48 .panel-button StIcon { icon-size: 48px; } -.just-perfection-api-panel-icon-size49 .system-status-icon, .just-perfection-api-panel-icon-size49 .panel-button StIcon { icon-size: 49px; } -.just-perfection-api-panel-icon-size50 .system-status-icon, .just-perfection-api-panel-icon-size50 .panel-button StIcon { icon-size: 50px; } -.just-perfection-api-panel-icon-size51 .system-status-icon, .just-perfection-api-panel-icon-size51 .panel-button StIcon { icon-size: 51px; } -.just-perfection-api-panel-icon-size52 .system-status-icon, .just-perfection-api-panel-icon-size52 .panel-button StIcon { icon-size: 52px; } -.just-perfection-api-panel-icon-size53 .system-status-icon, .just-perfection-api-panel-icon-size53 .panel-button StIcon { icon-size: 53px; } -.just-perfection-api-panel-icon-size54 .system-status-icon, .just-perfection-api-panel-icon-size54 .panel-button StIcon { icon-size: 54px; } -.just-perfection-api-panel-icon-size55 .system-status-icon, .just-perfection-api-panel-icon-size55 .panel-button StIcon { icon-size: 55px; } -.just-perfection-api-panel-icon-size56 .system-status-icon, .just-perfection-api-panel-icon-size56 .panel-button StIcon { icon-size: 56px; } -.just-perfection-api-panel-icon-size57 .system-status-icon, .just-perfection-api-panel-icon-size57 .panel-button StIcon { icon-size: 57px; } -.just-perfection-api-panel-icon-size58 .system-status-icon, .just-perfection-api-panel-icon-size58 .panel-button StIcon { icon-size: 58px; } -.just-perfection-api-panel-icon-size59 .system-status-icon, .just-perfection-api-panel-icon-size59 .panel-button StIcon { icon-size: 59px; } -.just-perfection-api-panel-icon-size60 .system-status-icon, .just-perfection-api-panel-icon-size60 .panel-button StIcon { icon-size: 60px; } - -.just-perfection-api-controls-manager-spacing-size0 .controls-manager, .just-perfection-api-controls-manager-spacing-size0 .secondary-monitor-workspaces { spacing: 0; } -.just-perfection-api-controls-manager-spacing-size1 .controls-manager, .just-perfection-api-controls-manager-spacing-size1 .secondary-monitor-workspaces { spacing: 1px; } -.just-perfection-api-controls-manager-spacing-size2 .controls-manager, .just-perfection-api-controls-manager-spacing-size2 .secondary-monitor-workspaces { spacing: 2px; } -.just-perfection-api-controls-manager-spacing-size3 .controls-manager, .just-perfection-api-controls-manager-spacing-size3 .secondary-monitor-workspaces { spacing: 3px; } -.just-perfection-api-controls-manager-spacing-size4 .controls-manager, .just-perfection-api-controls-manager-spacing-size4 .secondary-monitor-workspaces { spacing: 4px; } -.just-perfection-api-controls-manager-spacing-size5 .controls-manager, .just-perfection-api-controls-manager-spacing-size5 .secondary-monitor-workspaces { spacing: 5px; } -.just-perfection-api-controls-manager-spacing-size6 .controls-manager, .just-perfection-api-controls-manager-spacing-size6 .secondary-monitor-workspaces { spacing: 6px; } -.just-perfection-api-controls-manager-spacing-size7 .controls-manager, .just-perfection-api-controls-manager-spacing-size7 .secondary-monitor-workspaces { spacing: 7px; } -.just-perfection-api-controls-manager-spacing-size8 .controls-manager, .just-perfection-api-controls-manager-spacing-size8 .secondary-monitor-workspaces { spacing: 8px; } -.just-perfection-api-controls-manager-spacing-size9 .controls-manager, .just-perfection-api-controls-manager-spacing-size9 .secondary-monitor-workspaces { spacing: 9px; } -.just-perfection-api-controls-manager-spacing-size10 .controls-manager, .just-perfection-api-controls-manager-spacing-size10 .secondary-monitor-workspaces { spacing: 10px; } -.just-perfection-api-controls-manager-spacing-size11 .controls-manager, .just-perfection-api-controls-manager-spacing-size11 .secondary-monitor-workspaces { spacing: 11px; } -.just-perfection-api-controls-manager-spacing-size12 .controls-manager, .just-perfection-api-controls-manager-spacing-size12 .secondary-monitor-workspaces { spacing: 12px; } -.just-perfection-api-controls-manager-spacing-size13 .controls-manager, .just-perfection-api-controls-manager-spacing-size13 .secondary-monitor-workspaces { spacing: 13px; } -.just-perfection-api-controls-manager-spacing-size14 .controls-manager, .just-perfection-api-controls-manager-spacing-size14 .secondary-monitor-workspaces { spacing: 14px; } -.just-perfection-api-controls-manager-spacing-size15 .controls-manager, .just-perfection-api-controls-manager-spacing-size15 .secondary-monitor-workspaces { spacing: 15px; } -.just-perfection-api-controls-manager-spacing-size16 .controls-manager, .just-perfection-api-controls-manager-spacing-size16 .secondary-monitor-workspaces { spacing: 16px; } -.just-perfection-api-controls-manager-spacing-size17 .controls-manager, .just-perfection-api-controls-manager-spacing-size17 .secondary-monitor-workspaces { spacing: 17px; } -.just-perfection-api-controls-manager-spacing-size18 .controls-manager, .just-perfection-api-controls-manager-spacing-size18 .secondary-monitor-workspaces { spacing: 18px; } -.just-perfection-api-controls-manager-spacing-size19 .controls-manager, .just-perfection-api-controls-manager-spacing-size19 .secondary-monitor-workspaces { spacing: 19px; } -.just-perfection-api-controls-manager-spacing-size20 .controls-manager, .just-perfection-api-controls-manager-spacing-size20 .secondary-monitor-workspaces { spacing: 20px; } -.just-perfection-api-controls-manager-spacing-size21 .controls-manager, .just-perfection-api-controls-manager-spacing-size21 .secondary-monitor-workspaces { spacing: 21px; } -.just-perfection-api-controls-manager-spacing-size22 .controls-manager, .just-perfection-api-controls-manager-spacing-size22 .secondary-monitor-workspaces { spacing: 22px; } -.just-perfection-api-controls-manager-spacing-size23 .controls-manager, .just-perfection-api-controls-manager-spacing-size23 .secondary-monitor-workspaces { spacing: 23px; } -.just-perfection-api-controls-manager-spacing-size24 .controls-manager, .just-perfection-api-controls-manager-spacing-size24 .secondary-monitor-workspaces { spacing: 24px; } -.just-perfection-api-controls-manager-spacing-size25 .controls-manager, .just-perfection-api-controls-manager-spacing-size25 .secondary-monitor-workspaces { spacing: 25px; } -.just-perfection-api-controls-manager-spacing-size26 .controls-manager, .just-perfection-api-controls-manager-spacing-size26 .secondary-monitor-workspaces { spacing: 26px; } -.just-perfection-api-controls-manager-spacing-size27 .controls-manager, .just-perfection-api-controls-manager-spacing-size27 .secondary-monitor-workspaces { spacing: 27px; } -.just-perfection-api-controls-manager-spacing-size28 .controls-manager, .just-perfection-api-controls-manager-spacing-size28 .secondary-monitor-workspaces { spacing: 28px; } -.just-perfection-api-controls-manager-spacing-size29 .controls-manager, .just-perfection-api-controls-manager-spacing-size29 .secondary-monitor-workspaces { spacing: 29px; } -.just-perfection-api-controls-manager-spacing-size30 .controls-manager, .just-perfection-api-controls-manager-spacing-size30 .secondary-monitor-workspaces { spacing: 30px; } -.just-perfection-api-controls-manager-spacing-size31 .controls-manager, .just-perfection-api-controls-manager-spacing-size31 .secondary-monitor-workspaces { spacing: 31px; } -.just-perfection-api-controls-manager-spacing-size32 .controls-manager, .just-perfection-api-controls-manager-spacing-size32 .secondary-monitor-workspaces { spacing: 32px; } -.just-perfection-api-controls-manager-spacing-size33 .controls-manager, .just-perfection-api-controls-manager-spacing-size33 .secondary-monitor-workspaces { spacing: 33px; } -.just-perfection-api-controls-manager-spacing-size34 .controls-manager, .just-perfection-api-controls-manager-spacing-size34 .secondary-monitor-workspaces { spacing: 34px; } -.just-perfection-api-controls-manager-spacing-size35 .controls-manager, .just-perfection-api-controls-manager-spacing-size35 .secondary-monitor-workspaces { spacing: 35px; } -.just-perfection-api-controls-manager-spacing-size36 .controls-manager, .just-perfection-api-controls-manager-spacing-size36 .secondary-monitor-workspaces { spacing: 36px; } -.just-perfection-api-controls-manager-spacing-size37 .controls-manager, .just-perfection-api-controls-manager-spacing-size37 .secondary-monitor-workspaces { spacing: 37px; } -.just-perfection-api-controls-manager-spacing-size38 .controls-manager, .just-perfection-api-controls-manager-spacing-size38 .secondary-monitor-workspaces { spacing: 38px; } -.just-perfection-api-controls-manager-spacing-size39 .controls-manager, .just-perfection-api-controls-manager-spacing-size39 .secondary-monitor-workspaces { spacing: 39px; } -.just-perfection-api-controls-manager-spacing-size40 .controls-manager, .just-perfection-api-controls-manager-spacing-size40 .secondary-monitor-workspaces { spacing: 40px; } -.just-perfection-api-controls-manager-spacing-size41 .controls-manager, .just-perfection-api-controls-manager-spacing-size41 .secondary-monitor-workspaces { spacing: 41px; } -.just-perfection-api-controls-manager-spacing-size42 .controls-manager, .just-perfection-api-controls-manager-spacing-size42 .secondary-monitor-workspaces { spacing: 42px; } -.just-perfection-api-controls-manager-spacing-size43 .controls-manager, .just-perfection-api-controls-manager-spacing-size43 .secondary-monitor-workspaces { spacing: 43px; } -.just-perfection-api-controls-manager-spacing-size44 .controls-manager, .just-perfection-api-controls-manager-spacing-size44 .secondary-monitor-workspaces { spacing: 44px; } -.just-perfection-api-controls-manager-spacing-size45 .controls-manager, .just-perfection-api-controls-manager-spacing-size45 .secondary-monitor-workspaces { spacing: 45px; } -.just-perfection-api-controls-manager-spacing-size46 .controls-manager, .just-perfection-api-controls-manager-spacing-size46 .secondary-monitor-workspaces { spacing: 46px; } -.just-perfection-api-controls-manager-spacing-size47 .controls-manager, .just-perfection-api-controls-manager-spacing-size47 .secondary-monitor-workspaces { spacing: 47px; } -.just-perfection-api-controls-manager-spacing-size48 .controls-manager, .just-perfection-api-controls-manager-spacing-size48 .secondary-monitor-workspaces { spacing: 48px; } -.just-perfection-api-controls-manager-spacing-size49 .controls-manager, .just-perfection-api-controls-manager-spacing-size49 .secondary-monitor-workspaces { spacing: 49px; } -.just-perfection-api-controls-manager-spacing-size50 .controls-manager, .just-perfection-api-controls-manager-spacing-size50 .secondary-monitor-workspaces { spacing: 50px; } -.just-perfection-api-controls-manager-spacing-size51 .controls-manager, .just-perfection-api-controls-manager-spacing-size51 .secondary-monitor-workspaces { spacing: 51px; } -.just-perfection-api-controls-manager-spacing-size52 .controls-manager, .just-perfection-api-controls-manager-spacing-size52 .secondary-monitor-workspaces { spacing: 52px; } -.just-perfection-api-controls-manager-spacing-size53 .controls-manager, .just-perfection-api-controls-manager-spacing-size53 .secondary-monitor-workspaces { spacing: 53px; } -.just-perfection-api-controls-manager-spacing-size54 .controls-manager, .just-perfection-api-controls-manager-spacing-size54 .secondary-monitor-workspaces { spacing: 54px; } -.just-perfection-api-controls-manager-spacing-size55 .controls-manager, .just-perfection-api-controls-manager-spacing-size55 .secondary-monitor-workspaces { spacing: 55px; } -.just-perfection-api-controls-manager-spacing-size56 .controls-manager, .just-perfection-api-controls-manager-spacing-size56 .secondary-monitor-workspaces { spacing: 56px; } -.just-perfection-api-controls-manager-spacing-size57 .controls-manager, .just-perfection-api-controls-manager-spacing-size57 .secondary-monitor-workspaces { spacing: 57px; } -.just-perfection-api-controls-manager-spacing-size58 .controls-manager, .just-perfection-api-controls-manager-spacing-size58 .secondary-monitor-workspaces { spacing: 58px; } -.just-perfection-api-controls-manager-spacing-size59 .controls-manager, .just-perfection-api-controls-manager-spacing-size59 .secondary-monitor-workspaces { spacing: 59px; } -.just-perfection-api-controls-manager-spacing-size60 .controls-manager, .just-perfection-api-controls-manager-spacing-size60 .secondary-monitor-workspaces { spacing: 60px; } -.just-perfection-api-controls-manager-spacing-size61 .controls-manager, .just-perfection-api-controls-manager-spacing-size61 .secondary-monitor-workspaces { spacing: 61px; } -.just-perfection-api-controls-manager-spacing-size62 .controls-manager, .just-perfection-api-controls-manager-spacing-size62 .secondary-monitor-workspaces { spacing: 62px; } -.just-perfection-api-controls-manager-spacing-size63 .controls-manager, .just-perfection-api-controls-manager-spacing-size63 .secondary-monitor-workspaces { spacing: 63px; } -.just-perfection-api-controls-manager-spacing-size64 .controls-manager, .just-perfection-api-controls-manager-spacing-size64 .secondary-monitor-workspaces { spacing: 64px; } -.just-perfection-api-controls-manager-spacing-size65 .controls-manager, .just-perfection-api-controls-manager-spacing-size65 .secondary-monitor-workspaces { spacing: 65px; } -.just-perfection-api-controls-manager-spacing-size66 .controls-manager, .just-perfection-api-controls-manager-spacing-size66 .secondary-monitor-workspaces { spacing: 66px; } -.just-perfection-api-controls-manager-spacing-size67 .controls-manager, .just-perfection-api-controls-manager-spacing-size67 .secondary-monitor-workspaces { spacing: 67px; } -.just-perfection-api-controls-manager-spacing-size68 .controls-manager, .just-perfection-api-controls-manager-spacing-size68 .secondary-monitor-workspaces { spacing: 68px; } -.just-perfection-api-controls-manager-spacing-size69 .controls-manager, .just-perfection-api-controls-manager-spacing-size69 .secondary-monitor-workspaces { spacing: 69px; } -.just-perfection-api-controls-manager-spacing-size70 .controls-manager, .just-perfection-api-controls-manager-spacing-size70 .secondary-monitor-workspaces { spacing: 70px; } -.just-perfection-api-controls-manager-spacing-size71 .controls-manager, .just-perfection-api-controls-manager-spacing-size71 .secondary-monitor-workspaces { spacing: 71px; } -.just-perfection-api-controls-manager-spacing-size72 .controls-manager, .just-perfection-api-controls-manager-spacing-size72 .secondary-monitor-workspaces { spacing: 72px; } -.just-perfection-api-controls-manager-spacing-size73 .controls-manager, .just-perfection-api-controls-manager-spacing-size73 .secondary-monitor-workspaces { spacing: 73px; } -.just-perfection-api-controls-manager-spacing-size74 .controls-manager, .just-perfection-api-controls-manager-spacing-size74 .secondary-monitor-workspaces { spacing: 74px; } -.just-perfection-api-controls-manager-spacing-size75 .controls-manager, .just-perfection-api-controls-manager-spacing-size75 .secondary-monitor-workspaces { spacing: 75px; } -.just-perfection-api-controls-manager-spacing-size76 .controls-manager, .just-perfection-api-controls-manager-spacing-size76 .secondary-monitor-workspaces { spacing: 76px; } -.just-perfection-api-controls-manager-spacing-size77 .controls-manager, .just-perfection-api-controls-manager-spacing-size77 .secondary-monitor-workspaces { spacing: 77px; } -.just-perfection-api-controls-manager-spacing-size78 .controls-manager, .just-perfection-api-controls-manager-spacing-size78 .secondary-monitor-workspaces { spacing: 78px; } -.just-perfection-api-controls-manager-spacing-size79 .controls-manager, .just-perfection-api-controls-manager-spacing-size79 .secondary-monitor-workspaces { spacing: 79px; } -.just-perfection-api-controls-manager-spacing-size80 .controls-manager, .just-perfection-api-controls-manager-spacing-size80 .secondary-monitor-workspaces { spacing: 80px; } -.just-perfection-api-controls-manager-spacing-size81 .controls-manager, .just-perfection-api-controls-manager-spacing-size81 .secondary-monitor-workspaces { spacing: 81px; } -.just-perfection-api-controls-manager-spacing-size82 .controls-manager, .just-perfection-api-controls-manager-spacing-size82 .secondary-monitor-workspaces { spacing: 82px; } -.just-perfection-api-controls-manager-spacing-size83 .controls-manager, .just-perfection-api-controls-manager-spacing-size83 .secondary-monitor-workspaces { spacing: 83px; } -.just-perfection-api-controls-manager-spacing-size84 .controls-manager, .just-perfection-api-controls-manager-spacing-size84 .secondary-monitor-workspaces { spacing: 84px; } -.just-perfection-api-controls-manager-spacing-size85 .controls-manager, .just-perfection-api-controls-manager-spacing-size85 .secondary-monitor-workspaces { spacing: 85px; } -.just-perfection-api-controls-manager-spacing-size86 .controls-manager, .just-perfection-api-controls-manager-spacing-size86 .secondary-monitor-workspaces { spacing: 86px; } -.just-perfection-api-controls-manager-spacing-size87 .controls-manager, .just-perfection-api-controls-manager-spacing-size87 .secondary-monitor-workspaces { spacing: 87px; } -.just-perfection-api-controls-manager-spacing-size88 .controls-manager, .just-perfection-api-controls-manager-spacing-size88 .secondary-monitor-workspaces { spacing: 88px; } -.just-perfection-api-controls-manager-spacing-size89 .controls-manager, .just-perfection-api-controls-manager-spacing-size89 .secondary-monitor-workspaces { spacing: 89px; } -.just-perfection-api-controls-manager-spacing-size90 .controls-manager, .just-perfection-api-controls-manager-spacing-size90 .secondary-monitor-workspaces { spacing: 90px; } -.just-perfection-api-controls-manager-spacing-size91 .controls-manager, .just-perfection-api-controls-manager-spacing-size91 .secondary-monitor-workspaces { spacing: 91px; } -.just-perfection-api-controls-manager-spacing-size92 .controls-manager, .just-perfection-api-controls-manager-spacing-size92 .secondary-monitor-workspaces { spacing: 92px; } -.just-perfection-api-controls-manager-spacing-size93 .controls-manager, .just-perfection-api-controls-manager-spacing-size93 .secondary-monitor-workspaces { spacing: 93px; } -.just-perfection-api-controls-manager-spacing-size94 .controls-manager, .just-perfection-api-controls-manager-spacing-size94 .secondary-monitor-workspaces { spacing: 94px; } -.just-perfection-api-controls-manager-spacing-size95 .controls-manager, .just-perfection-api-controls-manager-spacing-size95 .secondary-monitor-workspaces { spacing: 95px; } -.just-perfection-api-controls-manager-spacing-size96 .controls-manager, .just-perfection-api-controls-manager-spacing-size96 .secondary-monitor-workspaces { spacing: 96px; } -.just-perfection-api-controls-manager-spacing-size97 .controls-manager, .just-perfection-api-controls-manager-spacing-size97 .secondary-monitor-workspaces { spacing: 97px; } -.just-perfection-api-controls-manager-spacing-size98 .controls-manager, .just-perfection-api-controls-manager-spacing-size98 .secondary-monitor-workspaces { spacing: 98px; } -.just-perfection-api-controls-manager-spacing-size99 .controls-manager, .just-perfection-api-controls-manager-spacing-size99 .secondary-monitor-workspaces { spacing: 99px; } -.just-perfection-api-controls-manager-spacing-size100 .controls-manager, .just-perfection-api-controls-manager-spacing-size100 .secondary-monitor-workspaces { spacing: 100px; } -.just-perfection-api-controls-manager-spacing-size101 .controls-manager, .just-perfection-api-controls-manager-spacing-size101 .secondary-monitor-workspaces { spacing: 101px; } -.just-perfection-api-controls-manager-spacing-size102 .controls-manager, .just-perfection-api-controls-manager-spacing-size102 .secondary-monitor-workspaces { spacing: 102px; } -.just-perfection-api-controls-manager-spacing-size103 .controls-manager, .just-perfection-api-controls-manager-spacing-size103 .secondary-monitor-workspaces { spacing: 103px; } -.just-perfection-api-controls-manager-spacing-size104 .controls-manager, .just-perfection-api-controls-manager-spacing-size104 .secondary-monitor-workspaces { spacing: 104px; } -.just-perfection-api-controls-manager-spacing-size105 .controls-manager, .just-perfection-api-controls-manager-spacing-size105 .secondary-monitor-workspaces { spacing: 105px; } -.just-perfection-api-controls-manager-spacing-size106 .controls-manager, .just-perfection-api-controls-manager-spacing-size106 .secondary-monitor-workspaces { spacing: 106px; } -.just-perfection-api-controls-manager-spacing-size107 .controls-manager, .just-perfection-api-controls-manager-spacing-size107 .secondary-monitor-workspaces { spacing: 107px; } -.just-perfection-api-controls-manager-spacing-size108 .controls-manager, .just-perfection-api-controls-manager-spacing-size108 .secondary-monitor-workspaces { spacing: 108px; } -.just-perfection-api-controls-manager-spacing-size109 .controls-manager, .just-perfection-api-controls-manager-spacing-size109 .secondary-monitor-workspaces { spacing: 109px; } -.just-perfection-api-controls-manager-spacing-size110 .controls-manager, .just-perfection-api-controls-manager-spacing-size110 .secondary-monitor-workspaces { spacing: 110px; } -.just-perfection-api-controls-manager-spacing-size111 .controls-manager, .just-perfection-api-controls-manager-spacing-size111 .secondary-monitor-workspaces { spacing: 111px; } -.just-perfection-api-controls-manager-spacing-size112 .controls-manager, .just-perfection-api-controls-manager-spacing-size112 .secondary-monitor-workspaces { spacing: 112px; } -.just-perfection-api-controls-manager-spacing-size113 .controls-manager, .just-perfection-api-controls-manager-spacing-size113 .secondary-monitor-workspaces { spacing: 113px; } -.just-perfection-api-controls-manager-spacing-size114 .controls-manager, .just-perfection-api-controls-manager-spacing-size114 .secondary-monitor-workspaces { spacing: 114px; } -.just-perfection-api-controls-manager-spacing-size115 .controls-manager, .just-perfection-api-controls-manager-spacing-size115 .secondary-monitor-workspaces { spacing: 115px; } -.just-perfection-api-controls-manager-spacing-size116 .controls-manager, .just-perfection-api-controls-manager-spacing-size116 .secondary-monitor-workspaces { spacing: 116px; } -.just-perfection-api-controls-manager-spacing-size117 .controls-manager, .just-perfection-api-controls-manager-spacing-size117 .secondary-monitor-workspaces { spacing: 117px; } -.just-perfection-api-controls-manager-spacing-size118 .controls-manager, .just-perfection-api-controls-manager-spacing-size118 .secondary-monitor-workspaces { spacing: 118px; } -.just-perfection-api-controls-manager-spacing-size119 .controls-manager, .just-perfection-api-controls-manager-spacing-size119 .secondary-monitor-workspaces { spacing: 119px; } -.just-perfection-api-controls-manager-spacing-size120 .controls-manager, .just-perfection-api-controls-manager-spacing-size120 .secondary-monitor-workspaces { spacing: 120px; } -.just-perfection-api-controls-manager-spacing-size121 .controls-manager, .just-perfection-api-controls-manager-spacing-size121 .secondary-monitor-workspaces { spacing: 121px; } -.just-perfection-api-controls-manager-spacing-size122 .controls-manager, .just-perfection-api-controls-manager-spacing-size122 .secondary-monitor-workspaces { spacing: 122px; } -.just-perfection-api-controls-manager-spacing-size123 .controls-manager, .just-perfection-api-controls-manager-spacing-size123 .secondary-monitor-workspaces { spacing: 123px; } -.just-perfection-api-controls-manager-spacing-size124 .controls-manager, .just-perfection-api-controls-manager-spacing-size124 .secondary-monitor-workspaces { spacing: 124px; } -.just-perfection-api-controls-manager-spacing-size125 .controls-manager, .just-perfection-api-controls-manager-spacing-size125 .secondary-monitor-workspaces { spacing: 125px; } -.just-perfection-api-controls-manager-spacing-size126 .controls-manager, .just-perfection-api-controls-manager-spacing-size126 .secondary-monitor-workspaces { spacing: 126px; } -.just-perfection-api-controls-manager-spacing-size127 .controls-manager, .just-perfection-api-controls-manager-spacing-size127 .secondary-monitor-workspaces { spacing: 127px; } -.just-perfection-api-controls-manager-spacing-size128 .controls-manager, .just-perfection-api-controls-manager-spacing-size128 .secondary-monitor-workspaces { spacing: 128px; } -.just-perfection-api-controls-manager-spacing-size129 .controls-manager, .just-perfection-api-controls-manager-spacing-size129 .secondary-monitor-workspaces { spacing: 129px; } -.just-perfection-api-controls-manager-spacing-size130 .controls-manager, .just-perfection-api-controls-manager-spacing-size130 .secondary-monitor-workspaces { spacing: 130px; } -.just-perfection-api-controls-manager-spacing-size131 .controls-manager, .just-perfection-api-controls-manager-spacing-size131 .secondary-monitor-workspaces { spacing: 131px; } -.just-perfection-api-controls-manager-spacing-size132 .controls-manager, .just-perfection-api-controls-manager-spacing-size132 .secondary-monitor-workspaces { spacing: 132px; } -.just-perfection-api-controls-manager-spacing-size133 .controls-manager, .just-perfection-api-controls-manager-spacing-size133 .secondary-monitor-workspaces { spacing: 133px; } -.just-perfection-api-controls-manager-spacing-size134 .controls-manager, .just-perfection-api-controls-manager-spacing-size134 .secondary-monitor-workspaces { spacing: 134px; } -.just-perfection-api-controls-manager-spacing-size135 .controls-manager, .just-perfection-api-controls-manager-spacing-size135 .secondary-monitor-workspaces { spacing: 135px; } -.just-perfection-api-controls-manager-spacing-size136 .controls-manager, .just-perfection-api-controls-manager-spacing-size136 .secondary-monitor-workspaces { spacing: 136px; } -.just-perfection-api-controls-manager-spacing-size137 .controls-manager, .just-perfection-api-controls-manager-spacing-size137 .secondary-monitor-workspaces { spacing: 137px; } -.just-perfection-api-controls-manager-spacing-size138 .controls-manager, .just-perfection-api-controls-manager-spacing-size138 .secondary-monitor-workspaces { spacing: 138px; } -.just-perfection-api-controls-manager-spacing-size139 .controls-manager, .just-perfection-api-controls-manager-spacing-size139 .secondary-monitor-workspaces { spacing: 139px; } -.just-perfection-api-controls-manager-spacing-size140 .controls-manager, .just-perfection-api-controls-manager-spacing-size140 .secondary-monitor-workspaces { spacing: 140px; } -.just-perfection-api-controls-manager-spacing-size141 .controls-manager, .just-perfection-api-controls-manager-spacing-size141 .secondary-monitor-workspaces { spacing: 141px; } -.just-perfection-api-controls-manager-spacing-size142 .controls-manager, .just-perfection-api-controls-manager-spacing-size142 .secondary-monitor-workspaces { spacing: 142px; } -.just-perfection-api-controls-manager-spacing-size143 .controls-manager, .just-perfection-api-controls-manager-spacing-size143 .secondary-monitor-workspaces { spacing: 143px; } -.just-perfection-api-controls-manager-spacing-size144 .controls-manager, .just-perfection-api-controls-manager-spacing-size144 .secondary-monitor-workspaces { spacing: 144px; } -.just-perfection-api-controls-manager-spacing-size145 .controls-manager, .just-perfection-api-controls-manager-spacing-size145 .secondary-monitor-workspaces { spacing: 145px; } -.just-perfection-api-controls-manager-spacing-size146 .controls-manager, .just-perfection-api-controls-manager-spacing-size146 .secondary-monitor-workspaces { spacing: 146px; } -.just-perfection-api-controls-manager-spacing-size147 .controls-manager, .just-perfection-api-controls-manager-spacing-size147 .secondary-monitor-workspaces { spacing: 147px; } -.just-perfection-api-controls-manager-spacing-size148 .controls-manager, .just-perfection-api-controls-manager-spacing-size148 .secondary-monitor-workspaces { spacing: 148px; } -.just-perfection-api-controls-manager-spacing-size149 .controls-manager, .just-perfection-api-controls-manager-spacing-size149 .secondary-monitor-workspaces { spacing: 149px; } -.just-perfection-api-controls-manager-spacing-size150 .controls-manager, .just-perfection-api-controls-manager-spacing-size150 .secondary-monitor-workspaces { spacing: 150px; } - -.just-perfection-api-osd-position-top .osd-window { margin: 4em 2.5em; } -.just-perfection-api-osd-position-center .osd-window { margin: 4em 3.5em; } -.just-perfection-api-osd-position-bottom .osd-window { margin: 4em 3em; } - -.just-perfection-api-no-dash-separator .dash-separator, -.just-perfection-api-no-dash-app-running-dot #dash .app-well-app-running-dot -{ - width: 0; - height: 0; - spacing: 0; - padding: 0; - margin: 0; -} - -.just-perfection-api-no-workspaces-in-app-grid .workspace-background -{ - background-color: transparent; - box-shadow: 0 4px 16px 4px transparent; -} - -.just-perfection-api-no-power-icon .power-status StIcon -{ - width: 0; - height: 0; - padding: 0; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/behavior.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/behavior.ui deleted file mode 100755 index 3b7be5ea..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/behavior.ui +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - - <object class="AdwPreferencesPage" id="behavior"> - <property name="name">behavior</property> - <property name="title" translatable="yes">Behavior</property> - <property name="icon-name">applications-engineering-symbolic</property> - - <child> - <object class="AdwPreferencesGroup" id="behavior_group"> - <property name="title" translatable="yes">Behavior</property> - - <child> - <object class="AdwActionRow" id="workspace_wrap_around_row"> - <property name="title" translatable="yes">Workspace Wraparound</property> - <property name="subtitle" translatable="yes">Next workspace will be the first workspace when you are in the last workspace. and previous workspace will be the last workspace when you are in the first workspace.</property> - <property name="activatable-widget">workspace_wrap_around_switch</property> - <child> - <object class="GtkSwitch" id="workspace_wrap_around_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="workspace_peek_row"> - <property name="title" translatable="yes">Workspace Peek</property> - <property name="subtitle" translatable="yes">Whether the next and previous workspace should be visible in overview.</property> - <property name="activatable-widget">workspace_peek_switch</property> - <child> - <object class="GtkSwitch" id="workspace_peek_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="window_demands_attention_focus_row"> - <property name="title" translatable="yes">Window Demands Attention Focus</property> - <property name="subtitle" translatable="yes">Removes window is ready notification and focus on the window</property> - <property name="activatable-widget">window_demands_attention_focus_switch</property> - <child> - <object class="GtkSwitch" id="window_demands_attention_focus_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="window_maximized_on_create_row"> - <property name="title" translatable="yes">Window Maximized by Default</property> - <property name="subtitle" translatable="yes">Maximize all windows on creation</property> - <property name="activatable-widget">window_maximized_on_create_switch</property> - <child> - <object class="GtkSwitch" id="window_maximized_on_create_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="type_to_search_row"> - <property name="title" translatable="yes">Type to Search</property> - <property name="subtitle" translatable="yes">You can start search without search entry or even focusing on it in overview</property> - <property name="activatable-widget">type_to_search_switch</property> - <child> - <object class="GtkSwitch" id="type_to_search_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="workspace_switcher_should_show_row"> - <property name="title" translatable="yes">Always Show Workspace Switcher</property> - <property name="subtitle" translatable="yes">Shows workspace switcher even when only one workspace used with dynamic workspaces</property> - <property name="activatable-widget">workspace_switcher_should_show_switch</property> - <child> - <object class="GtkSwitch" id="workspace_switcher_should_show_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="overlay_key_row"> - <property name="title" translatable="yes">Overlay Key</property> - <property name="subtitle" translatable="yes">Disable overlay key (super key)</property> - <property name="activatable-widget">overlay_key_switch</property> - <child> - <object class="GtkSwitch" id="overlay_key_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="double_super_to_appgrid_row"> - <property name="title" translatable="yes">Double Super to App Grid</property> - <property name="subtitle" translatable="yes">Shows app grid when you double hit super key fast</property> - <property name="activatable-widget">double_super_to_appgrid_switch</property> - <property name="sensitive" bind-source="overlay_key_switch" bind-property="active" bind-flags="sync-create"/> - <child> - <object class="GtkSwitch" id="double_super_to_appgrid_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="switcher_popup_delay_row"> - <property name="title" translatable="yes">Popup Delay</property> - <property name="subtitle" translatable="yes">Removes the delay for all switcher popups like alt-tab, ctrl-alt-tab, keyboard layout, ...</property> - <property name="activatable-widget">switcher_popup_delay_switch</property> - <child> - <object class="GtkSwitch" id="switcher_popup_delay_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwComboRow" id="startup_status_row"> - <property name="title" translatable="yes">Startup Status</property> - <property name="subtitle" translatable="yes">When GNOME Shell is starting up for the first time</property> - <property name="model">startup_status_model</property> - </object> - </child> - - </object> - </child> - - </object> - - <object class="GtkStringList" id="startup_status_model"> - <items> - <item translatable="yes">Desktop</item> - <item translatable="yes">Overview</item> - </items> - </object> - -</interface> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/customize.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/customize.ui deleted file mode 100755 index 14fbbd38..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/customize.ui +++ /dev/null @@ -1,839 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - - <object class="AdwPreferencesPage" id="customize"> - <property name="name">customize</property> - <property name="title" translatable="yes">Customize</property> - <property name="icon-name">applications-utilities-symbolic</property> - - <child> - <object class="AdwPreferencesGroup" id="customize_group"> - <property name="title" translatable="yes">Customize</property> - - <child> - <object class="AdwComboRow" id="controls_manager_spacing_size_row"> - <property name="title" translatable="yes">Overview Spacing Size</property> - <property name="subtitle" translatable="yes">The spacing size for controls manager in overview</property> - <property name="model">controls_manager_spacing_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="workspace_background_corner_size_row"> - <property name="title" translatable="yes">Workspace Background Corner Size</property> - <property name="subtitle" translatable="yes">Workspace background corner size in overview</property> - <property name="model">workspace_background_corner_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="panel_size_row"> - <property name="title" translatable="yes">Panel Size</property> - <property name="model">panel_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="panel_icon_size_row"> - <property name="title" translatable="yes">Panel Icon Size</property> - <property name="model">panel_icon_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="panel_button_padding_size_row"> - <property name="title" translatable="yes">Panel Button Padding Size</property> - <property name="model">panel_button_padding_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="panel_indicator_padding_size_row"> - <property name="title" translatable="yes">Panel Indicator Padding Size</property> - <property name="model">panel_indicator_padding_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="top_panel_position_row"> - <property name="title" translatable="yes">Panel Position</property> - <property name="model">top_panel_position_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="clock_menu_position_row"> - <property name="title" translatable="yes">Clock Menu Position</property> - <property name="model">clock_menu_position_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="clock_menu_position_offset_row"> - <property name="title" translatable="yes">Clock Menu Position Offset</property> - <property name="model">clock_menu_position_offset_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="workspace_switcher_size_row"> - <property name="title" translatable="yes">Workspace Switcher Size</property> - <property name="model">workspace_switcher_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="animation_row"> - <property name="title" translatable="yes">Animation</property> - <property name="model">animation_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="dash_icon_size_row"> - <property name="title" translatable="yes">Dash Icon Size</property> - <property name="model">dash_icon_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="notification_banner_position_row"> - <property name="title" translatable="yes">Notification Banner Position</property> - <property name="subtitle" translatable="yes">Notification popup position when notifications show up on the screen</property> - <property name="model">notification_banner_position_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="osd_position_row"> - <property name="title" translatable="yes">OSD Position</property> - <property name="subtitle" translatable="yes">OSD position when on screen display shows up on the screen</property> - <property name="model">osd_position_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="alt_tab_window_preview_size_row"> - <property name="title" translatable="yes">Alt Tab Window Preview Size</property> - <property name="model">alt_tab_window_preview_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="alt_tab_small_icon_size_row"> - <property name="title" translatable="yes">Alt Tab Window Preview Icon Size</property> - <property name="model">alt_tab_small_icon_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="alt_tab_icon_size_row"> - <property name="title" translatable="yes">Alt Tab Icon Size</property> - <property name="model">alt_tab_icon_size_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="looking_glass_width_row"> - <property name="title" translatable="yes">Looking Glass Width</property> - <property name="model">looking_glass_width_model</property> - </object> - </child> - - <child> - <object class="AdwComboRow" id="looking_glass_height_row"> - <property name="title" translatable="yes">Looking Glass Height</property> - <property name="model">looking_glass_height_model</property> - </object> - </child> - - </object> - </child> - - </object> - - <object class="GtkStringList" id="controls_manager_spacing_size_model"> - <items> - <item translatable="yes">Default</item> - <item>1</item> - <item>2</item> - <item>3</item> - <item>4</item> - <item>5</item> - <item>6</item> - <item>7</item> - <item>8</item> - <item>9</item> - <item>10</item> - <item>11</item> - <item>12</item> - <item>13</item> - <item>14</item> - <item>15</item> - <item>16</item> - <item>17</item> - <item>18</item> - <item>19</item> - <item>20</item> - <item>21</item> - <item>22</item> - <item>23</item> - <item>24</item> - <item>25</item> - <item>26</item> - <item>27</item> - <item>28</item> - <item>29</item> - <item>30</item> - <item>31</item> - <item>32</item> - <item>33</item> - <item>34</item> - <item>35</item> - <item>36</item> - <item>37</item> - <item>38</item> - <item>39</item> - <item>40</item> - <item>41</item> - <item>42</item> - <item>43</item> - <item>44</item> - <item>45</item> - <item>46</item> - <item>47</item> - <item>48</item> - <item>49</item> - <item>50</item> - <item>51</item> - <item>52</item> - <item>53</item> - <item>54</item> - <item>55</item> - <item>56</item> - <item>57</item> - <item>58</item> - <item>59</item> - <item>60</item> - <item>61</item> - <item>62</item> - <item>63</item> - <item>64</item> - <item>65</item> - <item>66</item> - <item>67</item> - <item>68</item> - <item>69</item> - <item>70</item> - <item>71</item> - <item>72</item> - <item>73</item> - <item>74</item> - <item>75</item> - <item>76</item> - <item>77</item> - <item>78</item> - <item>79</item> - <item>80</item> - <item>81</item> - <item>82</item> - <item>83</item> - <item>84</item> - <item>85</item> - <item>86</item> - <item>87</item> - <item>88</item> - <item>89</item> - <item>90</item> - <item>91</item> - <item>92</item> - <item>93</item> - <item>94</item> - <item>95</item> - <item>96</item> - <item>97</item> - <item>98</item> - <item>99</item> - <item>100</item> - <item>101</item> - <item>102</item> - <item>103</item> - <item>104</item> - <item>105</item> - <item>106</item> - <item>107</item> - <item>108</item> - <item>109</item> - <item>110</item> - <item>111</item> - <item>112</item> - <item>113</item> - <item>114</item> - <item>115</item> - <item>116</item> - <item>117</item> - <item>118</item> - <item>119</item> - <item>120</item> - <item>121</item> - <item>122</item> - <item>123</item> - <item>124</item> - <item>125</item> - <item>126</item> - <item>127</item> - <item>128</item> - <item>129</item> - <item>130</item> - <item>131</item> - <item>132</item> - <item>133</item> - <item>134</item> - <item>135</item> - <item>136</item> - <item>137</item> - <item>138</item> - <item>139</item> - <item>140</item> - <item>141</item> - <item>142</item> - <item>143</item> - <item>144</item> - <item>145</item> - <item>146</item> - <item>147</item> - <item>148</item> - <item>149</item> - <item>150</item> - </items> - </object> - - <object class="GtkStringList" id="workspace_background_corner_size_model"> - <items> - <item translatable="yes">By Shell Theme</item> - <item>0px</item> - <item>1px</item> - <item>2px</item> - <item>3px</item> - <item>4px</item> - <item>5px</item> - <item>6px</item> - <item>7px</item> - <item>8px</item> - <item>9px</item> - <item>10px</item> - <item>11px</item> - <item>12px</item> - <item>13px</item> - <item>14px</item> - <item>15px</item> - <item>16px</item> - <item>17px</item> - <item>18px</item> - <item>19px</item> - <item>20px</item> - <item>21px</item> - <item>22px</item> - <item>23px</item> - <item>24px</item> - <item>25px</item> - <item>26px</item> - <item>27px</item> - <item>28px</item> - <item>29px</item> - <item>30px</item> - <item>31px</item> - <item>32px</item> - <item>33px</item> - <item>34px</item> - <item>35px</item> - <item>36px</item> - <item>37px</item> - <item>38px</item> - <item>39px</item> - <item>40px</item> - <item>41px</item> - <item>42px</item> - <item>43px</item> - <item>44px</item> - <item>45px</item> - <item>46px</item> - <item>47px</item> - <item>48px</item> - <item>49px</item> - <item>50px</item> - <item>51px</item> - <item>52px</item> - <item>53px</item> - <item>54px</item> - <item>55px</item> - <item>56px</item> - <item>57px</item> - <item>58px</item> - <item>59px</item> - <item>60px</item> - </items> - </object> - - - <object class="GtkStringList" id="panel_size_model"> - <items> - <item translatable="yes">By Shell Theme</item> - <item>1px</item> - <item>2px</item> - <item>3px</item> - <item>4px</item> - <item>5px</item> - <item>6px</item> - <item>7px</item> - <item>8px</item> - <item>9px</item> - <item>10px</item> - <item>11px</item> - <item>12px</item> - <item>13px</item> - <item>14px</item> - <item>15px</item> - <item>16px</item> - <item>17px</item> - <item>18px</item> - <item>19px</item> - <item>20px</item> - <item>21px</item> - <item>22px</item> - <item>23px</item> - <item>24px</item> - <item>25px</item> - <item>26px</item> - <item>27px</item> - <item>28px</item> - <item>29px</item> - <item>30px</item> - <item>31px</item> - <item>32px</item> - <item>33px</item> - <item>34px</item> - <item>35px</item> - <item>36px</item> - <item>37px</item> - <item>38px</item> - <item>39px</item> - <item>40px</item> - <item>41px</item> - <item>42px</item> - <item>43px</item> - <item>44px</item> - <item>45px</item> - <item>46px</item> - <item>47px</item> - <item>48px</item> - <item>49px</item> - <item>50px</item> - <item>51px</item> - <item>52px</item> - <item>53px</item> - <item>54px</item> - <item>55px</item> - <item>56px</item> - <item>57px</item> - <item>58px</item> - <item>59px</item> - <item>60px</item> - </items> - </object> - - <object class="GtkStringList" id="panel_icon_size_model"> - <items> - <item translatable="yes">By Shell Theme</item> - <item>1px</item> - <item>2px</item> - <item>3px</item> - <item>4px</item> - <item>5px</item> - <item>6px</item> - <item>7px</item> - <item>8px</item> - <item>9px</item> - <item>10px</item> - <item>11px</item> - <item>12px</item> - <item>13px</item> - <item>14px</item> - <item>15px</item> - <item>16px</item> - <item>17px</item> - <item>18px</item> - <item>19px</item> - <item>20px</item> - <item>21px</item> - <item>22px</item> - <item>23px</item> - <item>24px</item> - <item>25px</item> - <item>26px</item> - <item>27px</item> - <item>28px</item> - <item>29px</item> - <item>30px</item> - <item>31px</item> - <item>32px</item> - <item>33px</item> - <item>34px</item> - <item>35px</item> - <item>36px</item> - <item>37px</item> - <item>38px</item> - <item>39px</item> - <item>40px</item> - <item>41px</item> - <item>42px</item> - <item>43px</item> - <item>44px</item> - <item>45px</item> - <item>46px</item> - <item>47px</item> - <item>48px</item> - <item>49px</item> - <item>50px</item> - <item>51px</item> - <item>52px</item> - <item>53px</item> - <item>54px</item> - <item>55px</item> - <item>56px</item> - <item>57px</item> - <item>58px</item> - <item>59px</item> - <item>60px</item> - </items> - </object> - - <object class="GtkStringList" id="panel_button_padding_size_model"> - <items> - <item translatable="yes">By Shell Theme</item> - <item>0px</item> - <item>1px</item> - <item>2px</item> - <item>3px</item> - <item>4px</item> - <item>5px</item> - <item>6px</item> - <item>7px</item> - <item>8px</item> - <item>9px</item> - <item>10px</item> - <item>11px</item> - <item>12px</item> - <item>13px</item> - <item>14px</item> - <item>15px</item> - <item>16px</item> - <item>17px</item> - <item>18px</item> - <item>19px</item> - <item>20px</item> - <item>21px</item> - <item>22px</item> - <item>23px</item> - <item>24px</item> - <item>25px</item> - <item>26px</item> - <item>27px</item> - <item>28px</item> - <item>29px</item> - <item>30px</item> - <item>31px</item> - <item>32px</item> - <item>33px</item> - <item>34px</item> - <item>35px</item> - <item>36px</item> - <item>37px</item> - <item>38px</item> - <item>39px</item> - <item>40px</item> - <item>41px</item> - <item>42px</item> - <item>43px</item> - <item>44px</item> - <item>45px</item> - <item>46px</item> - <item>47px</item> - <item>48px</item> - <item>49px</item> - <item>50px</item> - <item>51px</item> - <item>52px</item> - <item>53px</item> - <item>54px</item> - <item>55px</item> - <item>56px</item> - <item>57px</item> - <item>58px</item> - <item>59px</item> - <item>60px</item> - </items> - </object> - - <object class="GtkStringList" id="panel_indicator_padding_size_model"> - <items> - <item translatable="yes">By Shell Theme</item> - <item>0px</item> - <item>1px</item> - <item>2px</item> - <item>3px</item> - <item>4px</item> - <item>5px</item> - <item>6px</item> - <item>7px</item> - <item>8px</item> - <item>9px</item> - <item>10px</item> - <item>11px</item> - <item>12px</item> - <item>13px</item> - <item>14px</item> - <item>15px</item> - <item>16px</item> - <item>17px</item> - <item>18px</item> - <item>19px</item> - <item>20px</item> - <item>21px</item> - <item>22px</item> - <item>23px</item> - <item>24px</item> - <item>25px</item> - <item>26px</item> - <item>27px</item> - <item>28px</item> - <item>29px</item> - <item>30px</item> - <item>31px</item> - <item>32px</item> - <item>33px</item> - <item>34px</item> - <item>35px</item> - <item>36px</item> - <item>37px</item> - <item>38px</item> - <item>39px</item> - <item>40px</item> - <item>41px</item> - <item>42px</item> - <item>43px</item> - <item>44px</item> - <item>45px</item> - <item>46px</item> - <item>47px</item> - <item>48px</item> - <item>49px</item> - <item>50px</item> - <item>51px</item> - <item>52px</item> - <item>53px</item> - <item>54px</item> - <item>55px</item> - <item>56px</item> - <item>57px</item> - <item>58px</item> - <item>59px</item> - <item>60px</item> - </items> - </object> - - <object class="GtkStringList" id="top_panel_position_model"> - <items> - <item translatable="yes">Top</item> - <item translatable="yes">Bottom</item> - </items> - </object> - - <object class="GtkStringList" id="clock_menu_position_model"> - <items> - <item translatable="yes">Center</item> - <item translatable="yes">Right</item> - <item translatable="yes">Left</item> - </items> - </object> - - <object class="GtkStringList" id="clock_menu_position_offset_model"> - <items> - <item>0</item> - <item>1</item> - <item>2</item> - <item>3</item> - <item>4</item> - <item>5</item> - <item>6</item> - <item>7</item> - <item>8</item> - <item>9</item> - <item>10</item> - <item>11</item> - <item>12</item> - <item>13</item> - <item>14</item> - <item>15</item> - <item>16</item> - <item>17</item> - <item>18</item> - <item>19</item> - <item>20</item> - </items> - </object> - - <object class="GtkStringList" id="workspace_switcher_size_model"> - <items> - <item translatable="yes">Default</item> - <item>1%</item> - <item>2%</item> - <item>3%</item> - <item>4%</item> - <item>5%</item> - <item>6%</item> - <item>7%</item> - <item>8%</item> - <item>9%</item> - <item>10%</item> - <item>11%</item> - <item>12%</item> - <item>13%</item> - <item>14%</item> - <item>15%</item> - <item>16%</item> - <item>17%</item> - <item>18%</item> - <item>19%</item> - <item>20%</item> - <item>21%</item> - <item>22%</item> - <item>23%</item> - <item>24%</item> - <item>25%</item> - <item>26%</item> - <item>27%</item> - <item>28%</item> - <item>29%</item> - <item>30%</item> - </items> - </object> - - <object class="GtkStringList" id="animation_model"> - <items> - <item translatable="yes">No Animation</item> - <item translatable="yes">Default Speed</item> - <item translatable="yes">Almost None</item> - <item translatable="yes">Fastest</item> - <item translatable="yes">Faster</item> - <item translatable="yes">Fast</item> - <item translatable="yes">Slow</item> - <item translatable="yes">Slower</item> - <item translatable="yes">Slowest</item> - </items> - </object> - - <object class="GtkStringList" id="dash_icon_size_model"> - <items> - <item translatable="yes">Default</item> - <item>16px</item> - <item>22px</item> - <item>24px</item> - <item>32px</item> - <item>40px</item> - <item>48px</item> - <item>56px</item> - <item>64px</item> - </items> - </object> - - <object class="GtkStringList" id="notification_banner_position_model"> - <items> - <item translatable="yes">Top Start</item> - <item translatable="yes">Top Center</item> - <item translatable="yes">Top End</item> - <item translatable="yes">Bottom Start</item> - <item translatable="yes">Bottom Center</item> - <item translatable="yes">Bottom End</item> - </items> - </object> - - <object class="GtkStringList" id="osd_position_model"> - <items> - <item translatable="yes">Default</item> - <item translatable="yes">Top Start</item> - <item translatable="yes">Top Center</item> - <item translatable="yes">Top End</item> - <item translatable="yes">Bottom Start</item> - <item translatable="yes">Bottom Center</item> - <item translatable="yes">Bottom End</item> - <item translatable="yes">Center Start</item> - <item translatable="yes">Center</item> - <item translatable="yes">Center End</item> - </items> - </object> - - <object class="GtkStringList" id="alt_tab_window_preview_size_model"> - <items> - <item translatable="yes">Default</item> - <item>32</item> - <item>64</item> - <item>128</item> - <item>256</item> - <item>512</item> - </items> - </object> - - <object class="GtkStringList" id="alt_tab_small_icon_size_model"> - <items> - <item translatable="yes">Default</item> - <item>32</item> - <item>64</item> - <item>128</item> - <item>256</item> - <item>512</item> - </items> - </object> - - <object class="GtkStringList" id="alt_tab_icon_size_model"> - <items> - <item translatable="yes">Default</item> - <item>32</item> - <item>64</item> - <item>128</item> - <item>256</item> - <item>512</item> - </items> - </object> - - <object class="GtkStringList" id="looking_glass_width_model"> - <items> - <item translatable="yes">Default</item> - <item>10%</item> - <item>20%</item> - <item>30%</item> - <item>40%</item> - <item>50%</item> - <item>60%</item> - <item>70%</item> - <item>80%</item> - <item>90%</item> - </items> - </object> - - <object class="GtkStringList" id="looking_glass_height_model"> - <items> - <item translatable="yes">Default</item> - <item>10%</item> - <item>20%</item> - <item>30%</item> - <item>40%</item> - <item>50%</item> - <item>60%</item> - <item>70%</item> - <item>80%</item> - <item>90%</item> - </items> - </object> - -</interface> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/icons.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/icons.ui deleted file mode 100755 index 9b83d2a9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/icons.ui +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - - <object class="AdwPreferencesPage" id="icons"> - <property name="name">icons</property> - <property name="title" translatable="yes">Icons</property> - <property name="icon-name">emblem-photos-symbolic</property> - - <child> - <object class="AdwPreferencesGroup" id="icons_group"> - <property name="title" translatable="yes">Icons</property> - - <child> - <object class="AdwActionRow" id="panel_notification_icon_row"> - <property name="title" translatable="yes">Panel Notification Icon</property> - <property name="activatable-widget">panel_notification_icon_switch</property> - <child> - <object class="GtkSwitch" id="panel_notification_icon_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="power_icon_row"> - <property name="title" translatable="yes">Power Icon</property> - <property name="activatable-widget">power_icon_switch</property> - <child> - <object class="GtkSwitch" id="power_icon_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="window_picker_icon_row"> - <property name="title" translatable="yes">Window Picker Icon</property> - <property name="subtitle" translatable="yes">The icon under window preview in overview</property> - <property name="activatable-widget">window_picker_icon_switch</property> - <child> - <object class="GtkSwitch" id="window_picker_icon_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - </object> - </child> - - </object> - -</interface> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/profile.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/profile.ui deleted file mode 100755 index 6175b344..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/profile.ui +++ /dev/null @@ -1,153 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - - <object class="AdwPreferencesPage" id="profile"> - <property name="name">profile</property> - <property name="title" translatable="yes">Profile</property> - <property name="icon-name">view-list-symbolic</property> - - <child> - <object class="AdwPreferencesGroup" id="profile_group"> - <property name="title" translatable="yes">Profile</property> - - <child> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="valign">center</property> - <property name="label" translatable="yes">You can choose between pre-defined profiles or you can simply use your own customized settings</property> - <property name="xalign">0</property> - <property name="wrap">True</property> - <property name="width-chars">0</property> - <property name="margin-top">12</property> - <property name="margin-bottom">12</property> - <style> - <class name="dim-label"/> - </style> - <attributes> - <attribute name="scale" value="0.9"/> - </attributes> - </object> - </child> - - <child> - <object class="GtkBox"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="hexpand">0</property> - <property name="vexpand">0</property> - <child> - <object class="GtkToggleButton" id="profile_default"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="label" translatable="yes">Default</property> - <property name="active">1</property> - <property name="hexpand">1</property> - <property name="vexpand">1</property> - </object> - </child> - <child> - <object class="GtkToggleButton" id="profile_custom"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="label" translatable="yes">Custom</property> - <property name="group">profile_default</property> - <property name="hexpand">1</property> - <property name="vexpand">1</property> - </object> - </child> - <child> - <object class="GtkToggleButton" id="profile_minimal"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="label" translatable="yes">Minimal</property> - <property name="group">profile_default</property> - <property name="hexpand">1</property> - <property name="vexpand">1</property> - </object> - </child> - <child> - <object class="GtkToggleButton" id="profile_superminimal"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="label" translatable="yes">Super Minimal</property> - <property name="group">profile_default</property> - <property name="hexpand">1</property> - <property name="vexpand">1</property> - </object> - </child> - <style> - <class name="linked"/> - </style> - </object> - </child> - - </object> - </child> - - <child> - <object class="AdwPreferencesGroup" id="override_group"> - <property name="title" translatable="yes">Override</property> - - <child> - <object class="AdwActionRow" id="theme_row"> - <property name="title" translatable="yes">Shell Theme</property> - <property name="subtitle" translatable="yes">Overrides the shell theme partially to create a minimal desktop</property> - <property name="activatable-widget">theme_switch</property> - <child> - <object class="GtkSwitch" id="theme_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - </object> - </child> - - <child> - <object class="AdwPreferencesGroup" id="support_group"> - <property name="title" translatable="yes">Links</property> - - <child> - <object class="AdwActionRow"> - <property name="title" translatable="yes">Bug Report</property> - <property name="activatable-widget">bug_report_linkbutton</property> - <child> - <object class="GtkLinkButton" id="bug_report_linkbutton"> - <property name="uri">https://gitlab.gnome.org/jrahmatzadeh/just-perfection/-/issues</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow"> - <property name="title" translatable="yes">Support via Patreon</property> - <property name="activatable-widget">patreon_linkbutton</property> - <child> - <object class="GtkLinkButton" id="patreon_linkbutton"> - <property name="uri">https://www.patreon.com/justperfection</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow"> - <property name="title" translatable="yes">Support via Buy Me a Coffee</property> - <property name="activatable-widget">buymeacoffee_linkbutton</property> - <child> - <object class="GtkLinkButton" id="buymeacoffee_linkbutton"> - <property name="uri">https://www.buymeacoffee.com/justperfection</property> - </object> - </child> - </object> - </child>" - - </object> - </child> - - </object> - -</interface> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/visibility.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/visibility.ui deleted file mode 100755 index e895dea7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/just-perfection-desktop@just-perfection/ui/adw/visibility.ui +++ /dev/null @@ -1,369 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - - <object class="AdwPreferencesPage" id="visibility"> - <property name="name">visibility</property> - <property name="title" translatable="yes">Visibility</property> - <property name="icon-name">weather-clear-symbolic</property> - - <child> - <object class="AdwPreferencesGroup" id="visibility_group"> - <property name="title" translatable="yes">Visibility</property> - - <child> - <object class="AdwActionRow" id="panel_row"> - <property name="title" translatable="yes">Panel</property> - <property name="activatable-widget">panel_switch</property> - <child> - <object class="GtkSwitch" id="panel_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="panel_in_overview_row"> - <property name="title" translatable="yes">Panel in Overview</property> - <property name="activatable-widget">panel_in_overview_switch</property> - <property name="sensitive" bind-source="panel_switch" bind-property="active" bind-flags="invert-boolean|sync-create"/> - <child> - <object class="GtkSwitch" id="panel_in_overview_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="activities_button_row"> - <property name="title" translatable="yes">Activities Button</property> - <property name="subtitle" translatable="yes">Button in panel to toggle overview visibility</property> - <property name="activatable-widget">activities_button_switch</property> - <child> - <object class="GtkSwitch" id="activities_button_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="clock_menu_row"> - <property name="title" translatable="yes">Clock Menu</property> - <property name="subtitle" translatable="yes">Also known as date menu shows date and time in panel</property> - <property name="activatable-widget">clock_menu_switch</property> - <child> - <object class="GtkSwitch" id="clock_menu_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="keyboard_layout_row"> - <property name="title" translatable="yes">Keyboard Layout</property> - <property name="subtitle" translatable="yes">Keyboard Layout indicator button in panel</property> - <property name="activatable-widget">keyboard_layout_switch</property> - <child> - <object class="GtkSwitch" id="keyboard_layout_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="accessibility_menu_row"> - <property name="title" translatable="yes">Accessibility Menu</property> - <property name="subtitle" translatable="yes">Accessibility Menu indicator button in panel</property> - <property name="activatable-widget">accessibility_menu_switch</property> - <child> - <object class="GtkSwitch" id="accessibility_menu_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="quick_settings_row"> - <property name="title" translatable="yes">Quick Settings</property> - <property name="subtitle" translatable="yes">Quick settings menu in panel</property> - <property name="activatable-widget">quick_settings_switch</property> - <child> - <object class="GtkSwitch" id="quick_settings_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="screen_sharing_indicator_row"> - <property name="title" translatable="yes">Screen Sharing Indicator</property> - <property name="subtitle" translatable="yes">Screen sharing indicator in panel</property> - <property name="activatable-widget">screen_sharing_indicator_switch</property> - <child> - <object class="GtkSwitch" id="screen_sharing_indicator_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="screen_recording_indicator_row"> - <property name="title" translatable="yes">Screen Recording Indicator</property> - <property name="subtitle" translatable="yes">Screen recording indicator in panel</property> - <property name="activatable-widget">screen_recording_indicator_switch</property> - <child> - <object class="GtkSwitch" id="screen_recording_indicator_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="world_clock_row"> - <property name="title" translatable="yes">World Clock</property> - <property name="subtitle" translatable="yes">World clock in clock menu</property> - <property name="activatable-widget">world_clock_switch</property> - <child> - <object class="GtkSwitch" id="world_clock_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="weather_row"> - <property name="title" translatable="yes">Weather</property> - <property name="subtitle" translatable="yes">Weather in clock menu</property> - <property name="activatable-widget">weather_switch</property> - <child> - <object class="GtkSwitch" id="weather_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="calendar_row"> - <property name="title" translatable="yes">Calendar</property> - <property name="subtitle" translatable="yes">Calendar in clock menu</property> - <property name="activatable-widget">calendar_switch</property> - <child> - <object class="GtkSwitch" id="calendar_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="events_button_row"> - <property name="title" translatable="yes">Events</property> - <property name="subtitle" translatable="yes">Events button in clock menu</property> - <property name="activatable-widget">events_button_switch</property> - <child> - <object class="GtkSwitch" id="events_button_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="search_row"> - <property name="title" translatable="yes">Search</property> - <property name="subtitle" translatable="yes">Search entry in overview</property> - <property name="activatable-widget">search_switch</property> - <child> - <object class="GtkSwitch" id="search_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="dash_row"> - <property name="title" translatable="yes">Dash</property> - <property name="subtitle" translatable="yes">Dash holds favorite and opened applications icons</property> - <property name="activatable-widget">dash_switch</property> - <child> - <object class="GtkSwitch" id="dash_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="dash_separator_row"> - <property name="title" translatable="yes">Dash Separator</property> - <property name="subtitle" translatable="yes">Dash separator line that separates pin apps from unpin apps</property> - <property name="activatable-widget">dash_separator_switch</property> - <child> - <object class="GtkSwitch" id="dash_separator_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="dash_app_running_row"> - <property name="title" translatable="yes">Dash App Running Indicator</property> - <property name="subtitle" translatable="yes">The dot indicator in dash that shows the app is running</property> - <property name="activatable-widget">dash_app_running_switch</property> - <child> - <object class="GtkSwitch" id="dash_app_running_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="show_apps_button_row"> - <property name="title" translatable="yes">Show Applications Button</property> - <property name="subtitle" translatable="yes">Button in dash that toggles applications list visibility</property> - <property name="activatable-widget">show_apps_button_switch</property> - <child> - <object class="GtkSwitch" id="show_apps_button_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="osd_row"> - <property name="title" translatable="yes">On Screen Display (OSD)</property> - <property name="subtitle" translatable="yes">Volume and brightness on screen display when the change happens</property> - <property name="activatable-widget">osd_switch</property> - <child> - <object class="GtkSwitch" id="osd_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="workspace_popup_row"> - <property name="title" translatable="yes">Workspace Popup</property> - <property name="subtitle" translatable="yes">Popup that appears on the screen when you change the workspace</property> - <property name="activatable-widget">workspace_popup_switch</property> - <child> - <object class="GtkSwitch" id="workspace_popup_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="workspace_row"> - <property name="title" translatable="yes">Workspace Switcher</property> - <property name="subtitle" translatable="yes">Also refers to workspace thumbnails that you see in overview for selecting a workspace</property> - <property name="activatable-widget">workspace_switch</property> - <child> - <object class="GtkSwitch" id="workspace_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="workspaces_in_app_grid_row"> - <property name="title" translatable="yes">Workspaces App Grid</property> - <property name="subtitle" translatable="yes">Workspace boxes in app grid</property> - <property name="activatable-widget">workspaces_in_app_grid_switch</property> - <child> - <object class="GtkSwitch" id="workspaces_in_app_grid_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="window_preview_close_button_row"> - <property name="title" translatable="yes">Window Picker Close Button</property> - <property name="subtitle" translatable="yes">The close button on window preview in overview</property> - <property name="activatable-widget">window_preview_close_button_switch</property> - <child> - <object class="GtkSwitch" id="window_preview_close_button_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="window_preview_caption_row"> - <property name="title" translatable="yes">Window Picker Caption</property> - <property name="subtitle" translatable="yes">The text under window preview in overview</property> - <property name="activatable-widget">window_preview_caption_switch</property> - <child> - <object class="GtkSwitch" id="window_preview_caption_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="background_menu_row"> - <property name="title" translatable="yes">Background Menu</property> - <property name="subtitle" translatable="yes">When you right click on desktop background</property> - <property name="activatable-widget">background_menu_switch</property> - <child> - <object class="GtkSwitch" id="background_menu_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="ripple_box_row"> - <property name="title" translatable="yes">Ripple Box</property> - <property name="subtitle" translatable="yes">Hot corner animation effects</property> - <property name="activatable-widget">ripple_box_switch</property> - <child> - <object class="GtkSwitch" id="ripple_box_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - <child> - <object class="AdwActionRow" id="window_menu_take_screenshot_button_row"> - <property name="title" translatable="yes">Take Screenshot button in Window Menu</property> - <property name="subtitle" translatable="yes">Take screenshot button in title bar right click menu</property> - <property name="activatable-widget">window_menu_take_screenshot_button_switch</property> - <child> - <object class="GtkSwitch" id="window_menu_take_screenshot_button_switch"> - <property name="valign">center</property> - </object> - </child> - </object> - </child> - - </object> - </child> - - </object> - -</interface> - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/PrefsLib/adw.js b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/PrefsLib/adw.js deleted file mode 100755 index c331fc2b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/PrefsLib/adw.js +++ /dev/null @@ -1,597 +0,0 @@ -import Adw from 'gi://Adw'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; -import * as Config from 'resource:///org/gnome/Shell/Extensions/js/misc/config.js'; -import {gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; -import * as Constants from '../constants.js'; - -Gio._promisify(Gtk.FileDialog.prototype, "open", "open_finish"); -const IconGrid = GObject.registerClass(class LogoMenuIconGrid extends Gtk.FlowBox { - _init() { - super._init({ - row_spacing: 10, - column_spacing: 10, - vexpand: false, - hexpand: true, - valign: Gtk.Align.START, - halign: Gtk.Align.CENTER, - homogeneous: true, - selection_mode: Gtk.SelectionMode.SINGLE, - margin_top: 5, - }); - this.childrenCount = 0; - } - - add(widget) { - this.insert(widget, -1); - this.childrenCount++; - } -}); - -export const LogoMenuIconsPage = GObject.registerClass(class LogoMenuIconsWidget extends Adw.PreferencesPage { - _init(settings) { - super._init(); - this._settings = settings; - this.set_title('Icon'); - this.set_name('Icon'); - this.set_icon_name('emblem-photos-symbolic'); - - const symbolicIconGroup = new Adw.PreferencesGroup({ - title: _('Symbolic Icons'), - }); - - const colouredIconGroup = new Adw.PreferencesGroup({ - title: _('Coloured Icons'), - }); - - const iconSettingsGroup = new Adw.PreferencesGroup({ - title: _('Icon Settings'), - }); - - // Symbolic Icons - - const symbolicIconsRow = new Adw.ActionRow(); - - const symbolicIconsFlowBox = new IconGrid(); - symbolicIconsFlowBox.connect('child-activated', () => { - const selectedChild = symbolicIconsFlowBox.get_selected_children(); - const selectedChildIndex = selectedChild[0].get_index(); - this._settings.set_boolean('symbolic-icon', true); - this._settings.set_int('menu-button-icon-image', selectedChildIndex); - this._settings.set_boolean('use-custom-icon', false); - }); - Constants.SymbolicDistroIcons.forEach(icon => { - let iconName = icon.PATH.replace('/Resources/', ''); - iconName = iconName.replace('.svg', ''); - const iconImage = new Gtk.Image({ - icon_name: iconName, - pixel_size: 36, - }); - symbolicIconsFlowBox.add(iconImage); - }); - - symbolicIconsRow.set_child(symbolicIconsFlowBox); - - if (this._settings.get_boolean('symbolic-icon')) { - const symbolicChildren = symbolicIconsFlowBox.childrenCount; - for (let i = 0; i < symbolicChildren; i++) { - if (i === this._settings.get_int('menu-button-icon-image')) { - symbolicIconsFlowBox.select_child(symbolicIconsFlowBox.get_child_at_index(i)); - break; - } - } - } - - // Coloured Icons - - const colouredIconsRow = new Adw.ActionRow(); - - const colouredIconsFlowBox = new IconGrid(); - colouredIconsFlowBox.connect('child-activated', () => { - const selectedChild = colouredIconsFlowBox.get_selected_children(); - const selectedChildIndex = selectedChild[0].get_index(); - this._settings.set_int('menu-button-icon-image', selectedChildIndex); - this._settings.set_boolean('symbolic-icon', false); - this._settings.set_boolean('use-custom-icon', false); - }); - Constants.ColouredDistroIcons.forEach(icon => { - let iconName = icon.PATH.replace('/Resources/', ''); - iconName = iconName.replace('.svg', ''); - const iconImage = new Gtk.Image({ - icon_name: iconName, - pixel_size: 36, - }); - colouredIconsFlowBox.add(iconImage); - }); - - colouredIconsRow.set_child(colouredIconsFlowBox); - - if (!this._settings.get_boolean('symbolic-icon')) { - const children = colouredIconsFlowBox.childrenCount; - for (let i = 0; i < children; i++) { - if (i === this._settings.get_int('menu-button-icon-image')) { - colouredIconsFlowBox.select_child(colouredIconsFlowBox.get_child_at_index(i)); - break; - } - } - } - - // Icon Size Scale - - const menuButtonIconSizeRow = new Adw.ActionRow({ - title: _('Icon Size'), - }); - - const iconSize = this._settings.get_int('menu-button-icon-size'); - - const menuButtonIconSizeScale = new Gtk.Scale({ - orientation: Gtk.Orientation.HORIZONTAL, - adjustment: new Gtk.Adjustment({ - lower: 14, - upper: 64, - step_increment: 1, - page_increment: 1, - page_size: 0, - }), - digits: 0, - round_digits: 0, - hexpand: true, - draw_value: true, - value_pos: Gtk.PositionType.RIGHT, - }); - - menuButtonIconSizeScale.set_format_value_func((scale, value) => { - return `\t${value}px`; - }); - - menuButtonIconSizeScale.set_value(iconSize); - menuButtonIconSizeScale.connect('value-changed', () => { - this._settings.set_int('menu-button-icon-size', menuButtonIconSizeScale.get_value()); - }); - - menuButtonIconSizeRow.add_suffix(menuButtonIconSizeScale); - - const customIconRow = new Adw.ExpanderRow({ - title: _('Use Custom Icon'), - show_enable_switch: true, - enable_expansion: this._settings.get_boolean('use-custom-icon'), - }); - - customIconRow.connect('notify::enable-expansion', () => { - this._settings.set_boolean('use-custom-icon', customIconRow.enable_expansion); - }); - - this._settings.connect('changed::use-custom-icon', () => { - customIconRow.set_enable_expansion(this._settings.get_boolean('use-custom-icon')) - }); - - const customIconSelectionRow = new Adw.ActionRow({ - title: _('Selected Icon'), - }); - - const customIconButton = new Gtk.Button({ - icon_name: 'document-open-symbolic', - valign: Gtk.Align.CENTER, - }) - - const customIconPreview = new Gtk.Image({ - icon_name: "start-here-symbolic", - icon_size: 2 - }); - - if(this._settings.get_string('custom-icon-path')) - customIconPreview.set_from_file(this._settings.get_string('custom-icon-path')); - - customIconButton.connect('clicked', async () => { - try { - const filter = new Gtk.FileFilter({ - name: "Images", - }); - - filter.add_pixbuf_formats(); - - const fileDialog = new Gtk.FileDialog({ - title: _('Select a Custom Icon'), - modal: true, - default_filter: filter - }); - - const file = await fileDialog.open(customIconButton.get_root(), null); - if (file) { - const filename = file.get_path(); - this._settings.set_string("custom-icon-path", filename); - customIconPreview.set_from_file(filename); - console.log(`Selected custom icon: ${filename}`); - } - } catch (error) { - console.error('Error selecting custom icon:', error.message); - } - }); - - customIconSelectionRow.add_suffix(customIconPreview); - customIconSelectionRow.add_suffix(customIconButton); - customIconRow.add_row(customIconSelectionRow); - - // iconGroup - symbolicIconGroup.add(symbolicIconsRow); - colouredIconGroup.add(colouredIconsRow); - iconSettingsGroup.add(customIconRow); - iconSettingsGroup.add(menuButtonIconSizeRow); - - this.add(symbolicIconGroup); - this.add(colouredIconGroup); - this.add(iconSettingsGroup); - } -}); - -// Create all the customization options -export const LogoMenuOptionsPage = GObject.registerClass(class LogoMenuOptionsWidget extends Adw.PreferencesPage { - _init(settings) { - super._init(); - this._settings = settings; - this.set_title('Other Options'); - this.set_name('Other Options'); - this.set_icon_name('emblem-system-symbolic'); - - const prefGroup1 = new Adw.PreferencesGroup({ - title: _('Change Defaults'), - }); - - const prefGroup2 = new Adw.PreferencesGroup({ - title: _('Show/Hide Options'), - }); - - const prefGroup3 = new Adw.PreferencesGroup({ - title: _('Top Panel Options'), - }); - // Rows - - // Activities click type - - const clickType = this._settings.get_int('menu-button-icon-click-type'); - const menuButtonIconClickTypeRow = new Adw.ActionRow({ - title: _('Icon Click Type to open Activities'), - }); - - const menuButtonIconClickTypeCombo = new Gtk.ComboBoxText({ - valign: Gtk.Align.CENTER, - }); - menuButtonIconClickTypeCombo.append('1', _('Left Click ')); - menuButtonIconClickTypeCombo.append('2', _('Middle Click ')); - menuButtonIconClickTypeCombo.append('3', _('Right Click ')); - menuButtonIconClickTypeCombo.set_active_id(clickType.toString()); - - menuButtonIconClickTypeCombo.connect('changed', () => { - this._settings.set_int('menu-button-icon-click-type', parseInt(menuButtonIconClickTypeCombo.get_active_id())); - }); - - menuButtonIconClickTypeRow.add_suffix(menuButtonIconClickTypeCombo); - - // Extensions application choice - - const extensionApp = this._settings.get_string('menu-button-extensions-app'); - const extensionsAppRow = new Adw.ActionRow({ - title: _('Preferred Extensions Application'), - }); - - const extensionsAppCombo = new Gtk.ComboBoxText({ - valign: Gtk.Align.CENTER, - }); - extensionsAppCombo.append('org.gnome.Extensions.desktop', _('GNOME Extensions')); - extensionsAppCombo.append('com.mattjakeman.ExtensionManager.desktop', _('Extensions Manager')); - extensionsAppCombo.set_active_id(extensionApp.toString()); - - extensionsAppCombo.connect('changed', () => { - this._settings.set_string('menu-button-extensions-app', extensionsAppCombo.get_active_id()); - }); - - extensionsAppRow.add_suffix(extensionsAppCombo); - - // Choose Terminal - - const menuButtonTerminalRow = new Adw.ActionRow({ - title: _('Terminal'), - }); - - // Change Terminal and build it's option in prefs - const currentTerminal = this._settings.get_string('menu-button-terminal'); - - const changeTerminalInput = new Gtk.Entry({ - valign: Gtk.Align.CENTER, - }); - - changeTerminalInput.set_text(currentTerminal); - changeTerminalInput.connect('changed', () => { - this._settings.set_string('menu-button-terminal', changeTerminalInput.get_text()); - }); - - menuButtonTerminalRow.add_suffix(changeTerminalInput); - - // Change Software Center and build it's option in prefs - - const softwareCentreRow = new Adw.ActionRow({ - title: _('Software Center'), - }); - const currentSoftwareCenter = this._settings.get_string('menu-button-software-center'); - - const changeSoftwareCenterInput = new Gtk.Entry({ - valign: Gtk.Align.CENTER, - }); - - changeSoftwareCenterInput.set_text(currentSoftwareCenter); - changeSoftwareCenterInput.connect('changed', () => { - this._settings.set_string('menu-button-software-center', changeSoftwareCenterInput.get_text()); - }); - - softwareCentreRow.add_suffix(changeSoftwareCenterInput); - - // Change System Monitor and build it's option in prefs - - const systemMonitorRow = new Adw.ActionRow({ - title: _('System Monitor'), - }); - const currentSystemMonitor = this._settings.get_string('menu-button-system-monitor'); - - const changeSystemMonitorInput = new Gtk.Entry({ - valign: Gtk.Align.CENTER, - }); - - changeSystemMonitorInput.set_text(currentSystemMonitor); - changeSystemMonitorInput.connect('changed', () => { - this._settings.set_string('menu-button-system-monitor', changeSystemMonitorInput.get_text()); - }); - - systemMonitorRow.add_suffix(changeSystemMonitorInput); - - - // Power Options - const showPowerOptionsRow = new Adw.ActionRow({ - title: _('Enable Power Options'), - }); - const showPowerOptionsSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - }); - - showPowerOptionsSwitch.set_active(this._settings.get_boolean('show-power-options')); - showPowerOptionsSwitch.connect('notify::active', widget => { - this._settings.set_boolean('show-power-options', widget.get_active()); - }); - - showPowerOptionsRow.add_suffix(showPowerOptionsSwitch); - - // Toggle Force Quit option and build it's option in prefs - const forceQuitOptionrow = new Adw.ActionRow({ - title: _('Hide Force Quit option'), - }); - - const forceQuitOptionsSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - }); - - forceQuitOptionsSwitch.set_active(this._settings.get_boolean('hide-forcequit')); - forceQuitOptionsSwitch.connect('notify::active', widget => { - this._settings.set_boolean('hide-forcequit', widget.get_active()); - }); - - forceQuitOptionrow.add_suffix(forceQuitOptionsSwitch); - - - // Toggle Lock Screen option and build it's option in prefs - const lockScreenOptionRow = new Adw.ActionRow({ - title: _('Show Lock Screen option'), - }); - - const showLockScreenSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - }); - - showLockScreenSwitch.set_active(this._settings.get_boolean('show-lockscreen')); - showLockScreenSwitch.connect('notify::active', widget => { - this._settings.set_boolean('show-lockscreen', widget.get_active()); - }); - - lockScreenOptionRow.add_suffix(showLockScreenSwitch); - - // Toggle Software centre option and build it's option in prefs - const softwareCentreOptionRow = new Adw.ActionRow({ - title: _('Hide Software Centre option'), - }); - - const hideSoftwareCentreSwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - }); - - hideSoftwareCentreSwitch.set_active(this._settings.get_boolean('hide-softwarecentre')); - hideSoftwareCentreSwitch.connect('notify::active', widget => { - this._settings.set_boolean('hide-softwarecentre', widget.get_active()); - }); - - softwareCentreOptionRow.add_suffix(hideSoftwareCentreSwitch); - - // Activities Button visibility - const activitiesButtonVisiblityRow = new Adw.ActionRow({ - title: _('Show Activities Button'), - }); - - const activitiesButtonVisiblitySwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: this._settings.get_boolean('show-activities-button'), - }); - - activitiesButtonVisiblitySwitch.connect('notify::active', widget => { - this._settings.set_boolean('show-activities-button', widget.get_active()); - }); - - activitiesButtonVisiblityRow.add_suffix(activitiesButtonVisiblitySwitch); - - // Icon Shadow Visibility - const iconShadowVisibilityRow = new Adw.ActionRow({ - title: _('Hide Icon Shadow'), - }); - - const iconShadowRowVisiblitySwitch = new Gtk.Switch({ - valign: Gtk.Align.CENTER, - active: this._settings.get_boolean('hide-icon-shadow'), - }); - - iconShadowRowVisiblitySwitch.connect('notify::active', widget => { - this._settings.set_boolean('hide-icon-shadow', widget.get_active()); - }); - - iconShadowVisibilityRow.add_suffix(iconShadowRowVisiblitySwitch); - - // Pref Group - prefGroup1.add(menuButtonIconClickTypeRow); - prefGroup1.add(extensionsAppRow); - prefGroup1.add(menuButtonTerminalRow); - prefGroup1.add(softwareCentreRow); - prefGroup1.add(systemMonitorRow); - - prefGroup2.add(showPowerOptionsRow); - prefGroup2.add(forceQuitOptionrow); - prefGroup2.add(lockScreenOptionRow); - prefGroup2.add(softwareCentreOptionRow); - - prefGroup3.add(activitiesButtonVisiblityRow); - prefGroup3.add(iconShadowVisibilityRow); - - this.add(prefGroup1); - this.add(prefGroup2); - this.add(prefGroup3); - } -}); - -// Parts taken from Arc Menu -// Create the About page -export const AboutPage = GObject.registerClass(class LogoMenuAboutPage extends Adw.PreferencesPage { - _init(metadata) { - super._init({ - title: _('About'), - icon_name: 'info-symbolic', - }); - - const PROJECT_IMAGE = 'settings-logo-menu-logo'; - const EXTERNAL_LINK_ICON = 'adw-external-link-symbolic' - - const logoMenuLogoGroup = new Adw.PreferencesGroup(); - const logoMenuBox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - margin_top: 10, - margin_bottom: 10, - hexpand: false, - vexpand: false, - }); - - const projectImage = new Gtk.Image({ - margin_bottom: 15, - icon_name: PROJECT_IMAGE, - pixel_size: 100, - }); - - const logoMenuLabel = new Gtk.Label({ - label: `<span size="large"><b>${_('Logo Menu')}</b></span>`, - use_markup: true, - vexpand: true, - valign: Gtk.Align.FILL, - }); - - const projectDescriptionLabel = new Gtk.Label({ - label: _('Quick access menu for GNOME'), - hexpand: false, - vexpand: false, - margin_bottom: 5, - }); - - logoMenuBox.append(projectImage); - logoMenuBox.append(logoMenuLabel); - logoMenuBox.append(projectDescriptionLabel); - logoMenuLogoGroup.add(logoMenuBox); - - this.add(logoMenuLogoGroup); - // ----------------------------------------------------------------------- - - // Extension/OS Info Group------------------------------------------------ - const extensionInfoGroup = new Adw.PreferencesGroup(); - const logoMenuVersionRow = new Adw.ActionRow({ - title: _('Logo Menu Version'), - }); - let releaseVersion; - if (metadata['version-name']) - releaseVersion = metadata['version-name']; - else - releaseVersion = 'unknown'; - logoMenuVersionRow.add_suffix(new Gtk.Label({ - label: `${releaseVersion}`, - })); - - const gnomeVersionRow = new Adw.ActionRow({ - title: _('GNOME Version'), - }); - gnomeVersionRow.add_suffix(new Gtk.Label({ - label: `${Config.PACKAGE_VERSION.toString()}`, - })); - - const createdByRow = new Adw.ActionRow({ - title: _('Created with love by'), - }); - createdByRow.add_suffix(new Gtk.Label({ - label: 'Aryan Kaushik', - })); - - const matrixRoomRow = new Adw.ActionRow({ - title: _('Matrix/Element room'), - }); - matrixRoomRow.add_suffix(new Gtk.LinkButton({ - icon_name: EXTERNAL_LINK_ICON, - uri: 'https://matrix.to/#/#logo-menu:matrix.org', - })); - - const githubLinkRow = new Adw.ActionRow({ - title: 'GitHub', - }); - githubLinkRow.add_suffix(new Gtk.LinkButton({ - icon_name: EXTERNAL_LINK_ICON, - uri: 'https://github.com/Aryan20/LogoMenu', - })); - - const contributorRow = new Adw.ActionRow({ - title: _('Contributors'), - }); - contributorRow.add_suffix(new Gtk.LinkButton({ - icon_name: EXTERNAL_LINK_ICON, - uri: 'https://github.com/Aryan20/Logomenu/graphs/contributors' - })); - - extensionInfoGroup.add(logoMenuVersionRow); - extensionInfoGroup.add(gnomeVersionRow); - extensionInfoGroup.add(createdByRow); - extensionInfoGroup.add(githubLinkRow); - extensionInfoGroup.add(matrixRoomRow); - extensionInfoGroup.add(contributorRow); - - this.add(extensionInfoGroup); - // ----------------------------------------------------------------------- - - const warrantyLabel = _('This program comes with absolutely no warranty.'); - const urlLabel = _('See the %sGNU General Public License, version 2 or later%s for details.').format('<a href="https://gnu.org/licenses/old-licenses/gpl-2.0.html">', '</a>'); - - const gnuSoftwareGroup = new Adw.PreferencesGroup(); - const gnuSofwareLabel = new Gtk.Label({ - label: `<span size="small">${warrantyLabel}\n${urlLabel}</span>`, - use_markup: true, - justify: Gtk.Justification.CENTER, - }); - - const gnuSofwareLabelBox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - valign: Gtk.Align.END, - vexpand: true, - margin_top: 5, - margin_bottom: 10, - }); - gnuSofwareLabelBox.append(gnuSofwareLabel); - gnuSoftwareGroup.add(gnuSofwareLabelBox); - this.add(gnuSoftwareGroup); - } -}); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/almalinux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/almalinux-logo-symbolic.svg deleted file mode 100755 index 57c97aa6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/almalinux-logo-symbolic.svg +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="496" - height="496" - viewBox="0 0 131.23333 131.23334" - version="1.1" - id="svg4110" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <defs - id="defs4107" /> - <g - id="layer1"> - <g - id="g4141" - transform="matrix(2.0888265,0,0,2.0888265,2.234266,3.7573409)"> - <g - id="g45" - transform="matrix(1.0005035,0,0,1.0005035,-0.1541809,0.11907192)"> - <path - id="path22-6" - d="m 56.11382,33.731278 c 2.6,-0.2 4.7,1.5 4.9,4.1 0.2,2.7 -1.7,4.9 -4.3,5.1 -2.5,0.2 -4.7,-1.7 -4.9,-4.2 -0.2,-2.7 1.6,-4.7 4.3,-5 z" - class="st1" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path24-7" - d="m 24.51382,55.031278 c 0,-2.6 2,-4.6 4.4,-4.6 2.4,0 4.7,2.2 4.7,4.7 0,2.4 -2,4.5 -4.3,4.6 -2.9,0 -4.8,-1.8 -4.8,-4.7 z" - class="st2" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path26-5" - d="m 31.61382,25.831278 c -0.4,0.2 -0.6,-0.1 -0.7,-0.4 -3.7,-6.9 -2.6,-15.6000004 3.9,-20.8000004 1.7,-1.4 4.9,-1.7 6.3,-0.3 0.6,0.5 0.7,1.1 0.8,1.8 0.2,1.5 0.5,3 1.5,4.2000004 1.1,1.3 2.5,1.8 4.1,1.7 1.4,0 2.8,-0.2 3.7,1.4 0.5,0.9 0.3,4.4 -0.5,5.1 -0.4,0.3 -0.7,0.1 -1,0 -2.3,-0.9 -4.7,-0.9 -7.1,-0.5 -0.8,0.1 -1.2,-0.1 -1.2,-1 -0.1,-1.5 -0.4,-2.9 -1.2,-4.2 -1.5,-2.7 -4.3,-2.8 -6.1,-0.3 -1.5,2 -1.9,4.4 -2.3,6.8 -0.4,2.1 -0.3,4.3 -0.2,6.5 0,0 -0.1,0 0,0 z" - class="st3" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path28-3" - d="m 34.11382,27.331278 c -0.2,-0.3 -0.1,-0.6 0.2,-0.8 5.7,-5.2 14.2,-6.2 20.8,-1.1 1.7,1.4 2.8,4.3 1.9,6 -0.4,0.7 -0.9,1 -1.5,1.2 -1.4,0.6 -2.7,1.2 -3.6,2.5 -0.9,1.3 -1.1,2.8 -0.7,4.4 0.3,1.3 0.8,2.7 -0.5,3.9 -0.7,0.7 -4.1,1.3 -5,0.7 -0.4,-0.3 -0.3,-0.6 -0.2,-1 0.3,-2.5 -0.3,-4.8 -1.2,-7 -0.3,-0.8 -0.2,-1.2 0.6,-1.4 1.4,-0.4 2.7,-1.1 3.7,-2.1 2.2,-2.1 1.7,-4.8 -1.2,-6 -2.3,-1 -4.7,-0.8 -7,-0.6 -2.2,0.1 -4.3,0.7 -6.3,1.3 z" - class="st1" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path30-5" - d="m 32.81382,29.931278 c 0.3,-0.3 0.5,-0.2 0.8,0 6.6,4 10,11.9 7,19.6 -0.8,2 -3.4,4 -5.3,3.5 -0.8,-0.2 -1.2,-0.6 -1.6,-1.1 -0.9,-1.2 -1.9,-2.3 -3.4,-2.8 -1.6,-0.5 -3,-0.2 -4.4,0.6 -1.2,0.7 -2.4,1.6 -3.9,0.7 -0.9,-0.5 -2.4,-3.6 -2.1,-4.6 0.2,-0.4 0.6,-0.4 1,-0.4 2.5,-0.4 4.5,-1.6 6.4,-3.2 0.6,-0.5 1.1,-0.5 1.6,0.2 0.8,1.2 1.8,2.2 3.1,2.9 2.6,1.5 5.1,0.2 5.4,-2.8 0.3,-2.5 -0.6,-4.7 -1.4,-6.9 -0.9,-2 -2,-3.9 -3.2,-5.7 z" - class="st2" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path32-6" - d="m 29.61382,30.531278 c -0.4,2 -1.3,3.9 -2.5,5.6 -3.6,5.4 -8.8,7.6 -15.2,7 -2.2999997,-0.2 -4.1999997,-2.1 -4.3999997,-4 -0.1,-0.8 0.1,-1.4 0.6,-2 0.7,-0.9 1.3,-1.7 1.6,-2.8 0.5999997,-2.2 -0.2,-4 -1.8,-5.6 -2.2,-2.2 -1.9,-4.2 0.7,-5.8 0.3,-0.2 0.7,-0.4 1.1,-0.6 0.5999997,-0.3 1.0999997,-0.3 1.2999997,0.4 0.9,2.3 2.7,4 4.7,5.4 0.7,0.6 0.7,1 0.1,1.7 -1.2,1.3 -1.9,2.9 -2,4.7 -0.2,2.2 1.1,3.6 3.3,3.6 1.4,0 2.7,-0.5 3.9,-1.1 3.1,-1.6 5.5,-3.9 7.8,-6.3 0.3,-0.1 0.4,-0.3 0.8,-0.2 z" - class="st4" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path34-2" - d="m 13.21382,9.5312776 c 0.2,0 0.7,0.1 1.2,0.2 3.7,0.7000004 6,-0.6 7.2,-4.1 0.8,-2.3 2.5,-3 4.7,-1.8 0.1,0 0.1,0.1 0.2,0.1 2.3,1.3 2.3,1.5 0.9,3.5 -1.2,1.6 -1.8,3.4000004 -2.1,5.3000004 -0.2,1.1 -0.6,1.3 -1.6,0.9 -1.6,-0.6 -3.3,-0.6 -5,0 -1.9,0.6 -2.7,2.3 -2.1,4.2 0.8,2.5 3,3.6 4.9,4.9 1.9,1.3 4.1,2 6.2,2.9 0.3,0.1 0.8,0.1 0.7,0.6 -0.1,0.3 -0.5,0.3 -0.9,0.3 -4.5,0.2 -8.8,-0.5 -12.3,-3.5 -3.3,-2.7 -5.6999997,-6 -5.2999997,-10.6 0.2999997,-1.5 1.3999997,-2.6000004 3.2999997,-2.9000004 z" - class="st5" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path36-9" - d="m 5.0138203,37.631278 c -2.4,0.3 -4.80000003,-1.7 -5.00000003,-4.2 -0.2,-2.4 1.80000003,-4.8 4.10000003,-5 2.6,-0.3 5,1.5 5.2,3.9 0.1,2.3 -1.4,5.1 -4.3,5.3 z" - class="st4" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path38-1" - d="m 47.01382,2.0312776 c 2.5,-0.2 4.9,1.8 5.1,4.3 0.2,2.4 -1.8,4.7000004 -4.2,4.9000004 -2.6,0.2 -4.9,-1.7000004 -5.1,-4.2000004 -0.2,-2.5 1.6,-4.8 4.2,-5 z" - class="st3" - style="fill:#cccccc;fill-opacity:1" /> - <path - id="path40-2" - d="m 20.91382,3.9312776 c 0.3,2.6 -1.5,4.8 -4.2,5.2 -2.3,0.3 -4.7,-1.6 -5,-3.8 -0.3,-2.9 1.3,-4.99999996 4,-5.29999996 2.5,-0.3 4.9,1.59999996 5.2,3.89999996 z" - class="st5" - style="fill:#cccccc;fill-opacity:1" /> - </g> - </g> - </g> - <style - id="style2" - type="text/css"> - .st1{fill:#86da2f}.st2{fill:#24c2ff}.st3{fill:#ffcb12}.st4{fill:#0069da}.st5{fill:#ff4649} - </style> - <style - id="style2-3" - type="text/css"> - .st1{fill:#86da2f}.st2{fill:#24c2ff}.st3{fill:#ffcb12}.st4{fill:#0069da}.st5{fill:#ff4649} - </style> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/almalinux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/almalinux-logo.svg deleted file mode 100755 index de1a0364..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/almalinux-logo.svg +++ /dev/null @@ -1,75 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - width="496" - height="496" - viewBox="0 0 131.23333 131.23334" - version="1.1" - id="svg4110" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg"> - <defs - id="defs4107" /> - <g - id="layer1"> - <g - id="g4141" - transform="matrix(2.0888265,0,0,2.0888265,2.234266,3.7573409)"> - <g - id="g45" - transform="matrix(1.0005035,0,0,1.0005035,-0.1541809,0.11907192)"> - <path - id="path22-6" - d="m 56.11382,33.731278 c 2.6,-0.2 4.7,1.5 4.9,4.1 0.2,2.7 -1.7,4.9 -4.3,5.1 -2.5,0.2 -4.7,-1.7 -4.9,-4.2 -0.2,-2.7 1.6,-4.7 4.3,-5 z" - class="st1" - style="fill:#86da2f;fill-opacity:1" /> - <path - id="path24-7" - d="m 24.51382,55.031278 c 0,-2.6 2,-4.6 4.4,-4.6 2.4,0 4.7,2.2 4.7,4.7 0,2.4 -2,4.5 -4.3,4.6 -2.9,0 -4.8,-1.8 -4.8,-4.7 z" - class="st2" - style="fill:#24c2ff;fill-opacity:1" /> - <path - id="path26-5" - d="m 31.61382,25.831278 c -0.4,0.2 -0.6,-0.1 -0.7,-0.4 -3.7,-6.9 -2.6,-15.6000004 3.9,-20.8000004 1.7,-1.4 4.9,-1.7 6.3,-0.3 0.6,0.5 0.7,1.1 0.8,1.8 0.2,1.5 0.5,3 1.5,4.2000004 1.1,1.3 2.5,1.8 4.1,1.7 1.4,0 2.8,-0.2 3.7,1.4 0.5,0.9 0.3,4.4 -0.5,5.1 -0.4,0.3 -0.7,0.1 -1,0 -2.3,-0.9 -4.7,-0.9 -7.1,-0.5 -0.8,0.1 -1.2,-0.1 -1.2,-1 -0.1,-1.5 -0.4,-2.9 -1.2,-4.2 -1.5,-2.7 -4.3,-2.8 -6.1,-0.3 -1.5,2 -1.9,4.4 -2.3,6.8 -0.4,2.1 -0.3,4.3 -0.2,6.5 0,0 -0.1,0 0,0 z" - class="st3" - style="fill:#ffcb12;fill-opacity:1" /> - <path - id="path28-3" - d="m 34.11382,27.331278 c -0.2,-0.3 -0.1,-0.6 0.2,-0.8 5.7,-5.2 14.2,-6.2 20.8,-1.1 1.7,1.4 2.8,4.3 1.9,6 -0.4,0.7 -0.9,1 -1.5,1.2 -1.4,0.6 -2.7,1.2 -3.6,2.5 -0.9,1.3 -1.1,2.8 -0.7,4.4 0.3,1.3 0.8,2.7 -0.5,3.9 -0.7,0.7 -4.1,1.3 -5,0.7 -0.4,-0.3 -0.3,-0.6 -0.2,-1 0.3,-2.5 -0.3,-4.8 -1.2,-7 -0.3,-0.8 -0.2,-1.2 0.6,-1.4 1.4,-0.4 2.7,-1.1 3.7,-2.1 2.2,-2.1 1.7,-4.8 -1.2,-6 -2.3,-1 -4.7,-0.8 -7,-0.6 -2.2,0.1 -4.3,0.7 -6.3,1.3 z" - class="st1" - style="fill:#86da2f;fill-opacity:1" /> - <path - id="path30-5" - d="m 32.81382,29.931278 c 0.3,-0.3 0.5,-0.2 0.8,0 6.6,4 10,11.9 7,19.6 -0.8,2 -3.4,4 -5.3,3.5 -0.8,-0.2 -1.2,-0.6 -1.6,-1.1 -0.9,-1.2 -1.9,-2.3 -3.4,-2.8 -1.6,-0.5 -3,-0.2 -4.4,0.6 -1.2,0.7 -2.4,1.6 -3.9,0.7 -0.9,-0.5 -2.4,-3.6 -2.1,-4.6 0.2,-0.4 0.6,-0.4 1,-0.4 2.5,-0.4 4.5,-1.6 6.4,-3.2 0.6,-0.5 1.1,-0.5 1.6,0.2 0.8,1.2 1.8,2.2 3.1,2.9 2.6,1.5 5.1,0.2 5.4,-2.8 0.3,-2.5 -0.6,-4.7 -1.4,-6.9 -0.9,-2 -2,-3.9 -3.2,-5.7 z" - class="st2" - style="fill:#24c2ff;fill-opacity:1" /> - <path - id="path32-6" - d="m 29.61382,30.531278 c -0.4,2 -1.3,3.9 -2.5,5.6 -3.6,5.4 -8.8,7.6 -15.2,7 -2.2999997,-0.2 -4.1999997,-2.1 -4.3999997,-4 -0.1,-0.8 0.1,-1.4 0.6,-2 0.7,-0.9 1.3,-1.7 1.6,-2.8 0.5999997,-2.2 -0.2,-4 -1.8,-5.6 -2.2,-2.2 -1.9,-4.2 0.7,-5.8 0.3,-0.2 0.7,-0.4 1.1,-0.6 0.5999997,-0.3 1.0999997,-0.3 1.2999997,0.4 0.9,2.3 2.7,4 4.7,5.4 0.7,0.6 0.7,1 0.1,1.7 -1.2,1.3 -1.9,2.9 -2,4.7 -0.2,2.2 1.1,3.6 3.3,3.6 1.4,0 2.7,-0.5 3.9,-1.1 3.1,-1.6 5.5,-3.9 7.8,-6.3 0.3,-0.1 0.4,-0.3 0.8,-0.2 z" - class="st4" - style="fill:#0069da;fill-opacity:1" /> - <path - id="path34-2" - d="m 13.21382,9.5312776 c 0.2,0 0.7,0.1 1.2,0.2 3.7,0.7000004 6,-0.6 7.2,-4.1 0.8,-2.3 2.5,-3 4.7,-1.8 0.1,0 0.1,0.1 0.2,0.1 2.3,1.3 2.3,1.5 0.9,3.5 -1.2,1.6 -1.8,3.4000004 -2.1,5.3000004 -0.2,1.1 -0.6,1.3 -1.6,0.9 -1.6,-0.6 -3.3,-0.6 -5,0 -1.9,0.6 -2.7,2.3 -2.1,4.2 0.8,2.5 3,3.6 4.9,4.9 1.9,1.3 4.1,2 6.2,2.9 0.3,0.1 0.8,0.1 0.7,0.6 -0.1,0.3 -0.5,0.3 -0.9,0.3 -4.5,0.2 -8.8,-0.5 -12.3,-3.5 -3.3,-2.7 -5.6999997,-6 -5.2999997,-10.6 0.2999997,-1.5 1.3999997,-2.6000004 3.2999997,-2.9000004 z" - class="st5" - style="fill:#ff4649;fill-opacity:1" /> - <path - id="path36-9" - d="m 5.0138203,37.631278 c -2.4,0.3 -4.80000003,-1.7 -5.00000003,-4.2 -0.2,-2.4 1.80000003,-4.8 4.10000003,-5 2.6,-0.3 5,1.5 5.2,3.9 0.1,2.3 -1.4,5.1 -4.3,5.3 z" - class="st4" - style="fill:#0069da;fill-opacity:1" /> - <path - id="path38-1" - d="m 47.01382,2.0312776 c 2.5,-0.2 4.9,1.8 5.1,4.3 0.2,2.4 -1.8,4.7000004 -4.2,4.9000004 -2.6,0.2 -4.9,-1.7000004 -5.1,-4.2000004 -0.2,-2.5 1.6,-4.8 4.2,-5 z" - class="st3" - style="fill:#ffcb12;fill-opacity:1" /> - <path - id="path40-2" - d="m 20.91382,3.9312776 c 0.3,2.6 -1.5,4.8 -4.2,5.2 -2.3,0.3 -4.7,-1.6 -5,-3.8 -0.3,-2.9 1.3,-4.99999996 4,-5.29999996 2.5,-0.3 4.9,1.59999996 5.2,3.89999996 z" - class="st5" - style="fill:#ff4649;fill-opacity:1" /> - </g> - </g> - </g> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/arch-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/arch-logo-symbolic.svg deleted file mode 100755 index e1b12331..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/arch-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - id="svg8" - version="1.1" - height="496" - width="496" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:dc="http://purl.org/dc/elements/1.1/"> - <metadata - id="metadata14"> - <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> - <defs - id="defs12" /> - <path - id="path4" - d="m 247.93344,17.871894 c -20.49358,50.233214 -32.85373,83.091376 -55.67015,131.826236 13.9889,14.826 31.1605,32.09056 59.04738,51.59003 -29.98068,-12.33447 -50.43052,-24.71727 -65.71321,-37.56731 -29.20024,60.91971 -74.95051,147.69601 -167.7909,314.47259 72.96954,-42.11649 123.77827,-68.0824 176.49709,-77.99095 -2.26368,-9.73362 -3.55081,-20.26245 -3.46331,-31.24816 l 0.0805,-2.33732 c 1.15775,-46.73933 31.74236,-84.002 60.03547,-84.06511 28.29312,-0.0633 55.80715,46.15485 54.64917,92.8942 -0.2175,8.79569 -1.21012,17.25536 -2.94362,25.10278 52.1433,10.19855 103.4958,36.09772 175.4777,77.64456 -14.1938,-26.12472 -26.86242,-49.67506 -38.96013,-72.10451 -19.05704,-14.7673 -38.93365,-33.98597 -79.47881,-54.79276 27.86845,7.23979 47.82218,15.59244 63.3754,24.92903 C 300.07316,147.25839 290.11644,116.83076 247.92986,17.860386 Z" - style="fill:#cccccc;fill-rule:evenodd;stroke-width:11.50832653" /> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/arch-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/arch-logo.svg deleted file mode 100755 index 3a35f646..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/arch-logo.svg +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - id="svg8" - version="1.1" - height="496" - width="496" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:dc="http://purl.org/dc/elements/1.1/"> - <metadata - id="metadata14"> - <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> - <defs - id="defs12" /> - <path - id="path4" - d="m 247.93344,17.871894 c -20.49358,50.233214 -32.85373,83.091376 -55.67015,131.826236 13.9889,14.826 31.1605,32.09056 59.04738,51.59003 -29.98068,-12.33447 -50.43052,-24.71727 -65.71321,-37.56731 -29.20024,60.91971 -74.95051,147.69601 -167.7909,314.47259 72.96954,-42.11649 123.77827,-68.0824 176.49709,-77.99095 -2.26368,-9.73362 -3.55081,-20.26245 -3.46331,-31.24816 l 0.0805,-2.33732 c 1.15775,-46.73933 31.74236,-84.002 60.03547,-84.06511 28.29312,-0.0633 55.80715,46.15485 54.64917,92.8942 -0.2175,8.79569 -1.21012,17.25536 -2.94362,25.10278 52.1433,10.19855 103.4958,36.09772 175.4777,77.64456 -14.1938,-26.12472 -26.86242,-49.67506 -38.96013,-72.10451 -19.05704,-14.7673 -38.93365,-33.98597 -79.47881,-54.79276 27.86845,7.23979 47.82218,15.59244 63.3754,24.92903 C 300.07316,147.25839 290.11644,116.83076 247.92986,17.860386 Z" - style="fill:#1793d1;fill-rule:evenodd;stroke-width:11.50832653;fill-opacity:1" /> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/asahilinux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/asahilinux-logo-symbolic.svg deleted file mode 100755 index 58f25e1b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/asahilinux-logo-symbolic.svg +++ /dev/null @@ -1,90 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - id="svg8" - version="1.1" - height="496" - width="496" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:dc="http://purl.org/dc/elements/1.1/"> - <metadata - id="metadata14"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <defs - id="defs12"> - <linearGradient - id="linearGradient1402"> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="0" - id="stop1400" /> - </linearGradient> - </defs> - <g - style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" - id="g849" - transform="matrix(0.91717941,0,0,0.91717941,-16.480902,-15.836491)"> - <g - id="layer8" - style="display:inline" - transform="translate(287.5,550)" /> - <g - id="layer7" - style="display:inline" - transform="translate(287.5,550)"> - <g - style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" - id="g2591" - transform="matrix(1.0009916,0,0,1.0009916,-287.86695,-550.38088)"> - <g - id="g1560" - style="clip-rule:evenodd;display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" - transform="translate(-62.5,-6.5e-4)"> - <g - id="g1445" - style="fill:#000000;fill-opacity:1" - transform="translate(0,6.5e-4)"> - <path - style="color:#000000;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;paint-order:stroke markers fill" - d="m 452.45312,411.80078 c -32.06055,44.58529 -64.12109,89.17057 -96.18164,133.75586 42.48698,-30.0944 84.97396,-60.1888 127.46094,-90.2832 -10.42643,-14.49089 -20.85287,-28.98177 -31.2793,-43.47266 z" - id="path1291" /> - <path - style="color:#000000;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;paint-order:stroke markers fill" - d="m 390,325 c 0,39.4031 0,78.8062 0,118.2093 14.18877,-19.70087 28.37753,-39.40174 42.5663,-59.10261 C 418.37753,364.40446 404.18877,344.70223 390,325 Z" - id="path1289" /> - <path - style="color:#000000;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;paint-order:stroke markers fill" - d="m 476.23047,152.19531 c -40.78832,17.07445 -81.57684,34.1484 -122.36524,51.22266 C 408.4679,279.35565 463.07272,355.2918 517.67406,431.23044 545.11604,411.7923 572.55802,392.35416 600,372.91602 558.74349,299.34245 517.48698,225.76888 476.23047,152.19531 Z" - id="path1287" /> - <path - style="color:#000000;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;paint-order:stroke markers fill" - d="M 223.76953,152.19531 C 182.51302,225.76888 141.25651,299.34245 100,372.91602 c 82.5,58.43815 165,116.8763 247.5,175.31445 0,-114.7474 0,-229.49479 0,-344.24219 -41.24347,-17.26436 -82.48708,-34.52841 -123.73047,-51.79297 z" - id="path1285" /> - <path - style="color:#000000;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;paint-order:stroke markers fill" - d="m 352.5,108.39648 v 52.19336 L 329.46484,114.52148 228.57422,148.78516 350,199.61523 471.42578,148.78516 Z" - id="path1283" /> - <path - id="path1631-9" - style="color:#000000;clip-rule:evenodd;display:inline;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;paint-order:stroke markers fill" - d="m 390,25 c -12.5,9.615234 -25,19.230469 -37.5,28.845703 0,7.051432 0,14.102865 0,21.154297 15.83333,0 31.66667,0 47.5,0 -3.33333,-16.666667 -6.66667,-33.333333 -10,-50 z" /> - </g> - <path - id="path1633-6" - style="color:#000000;clip-rule:evenodd;display:inline;overflow:visible;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="m 347.5,26.25 c -15.08789,7.544271 -30.17578,15.088541 -45.26367,22.632812 15.08789,30.175783 30.17578,60.351568 45.26367,90.527348 0,-37.72005 0,-75.440107 0,-113.16016 z" /> - </g> - </g> - </g> - </g> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/asahilinux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/asahilinux-logo.svg deleted file mode 100755 index 42cf7f6b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/asahilinux-logo.svg +++ /dev/null @@ -1,72 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - id="svg8" - version="1.1" - height="496" - width="496" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:dc="http://purl.org/dc/elements/1.1/"> - <metadata - id="metadata14"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <defs - id="defs12" /> - <g - style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" - id="g849" - transform="matrix(0.91717941,0,0,0.91717941,-16.480902,-15.836491)"> - <g - id="layer8" - style="display:inline" - transform="translate(287.5,550)" /> - <g - id="layer7" - style="display:inline" - transform="translate(287.5,550)"> - <path - id="path1639" - style="color:#000000;overflow:visible;fill:#2c2c2c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="M 475,150 H 350 L 349.998,550 483.73242,455.27344 460,390 515.63477,432.67383 600,372.91602 Z" - transform="translate(-350,-550)" /> - <path - style="color:#000000;overflow:visible;fill:#d3506f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="M -250,-177.08333 C -166.66667,-118.05555 -83.333333,-59.027777 0,0 5.6168904,-20.318129 16.776706,-39.823731 15.408525,-61.428776 17.385993,-140.95252 19.363462,-220.47626 21.340931,-300 14.958616,-318.63132 1.1436116,-335.70762 0.15443549,-355.54282 -8.4459121,-369.69334 -32.776816,-369.88554 -47.284099,-378.91365 -65.55003,-385.68541 -83.435815,-394.4311 -101.93339,-400 c -7.68887,0 -15.37774,0 -23.06661,0 -41.66667,74.30556 -83.33333,148.61111 -125,222.91667 z" - id="path1627" /> - <path - style="color:#000000;overflow:visible;fill:#a61200;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="m -125,-400 c 41.666668,-14.15094 83.333332,-28.30189 125,-42.45283 19.801989,6.7252 39.603976,13.45041 59.405965,20.17561 -3.906867,5.09703 -24.217781,15.8645 -8.103858,17.85923 24.550851,1.71846 49.137783,2.84775 73.697893,4.41799 -41.666667,17.44186 -83.333333,34.88372 -125,52.32558" - id="path1629" /> - <path - style="color:#000000;overflow:visible;fill:#00a67c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="m -24.999998,-475 c 24.9999993333333,0 49.999999,0 74.999998,0 -3.333333,-16.66667 -6.666667,-33.33333 -10,-50 -21.666664,16.66667 -43.3333345,33.33333 -64.999998,50 z" - id="path1631" /> - <path - style="color:#000000;overflow:visible;fill:#edbb60;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="m 4.9025e-5,-400 c 3.25e-7,-41.66667 6.5e-7,-83.33333 9.75e-7,-125 -16.666686,8.33333 -33.333367,16.66667 -50.000053,25 16.666688,33.33333 33.333364,66.66667 50.000052025,100 z" - id="path1633" /> - <path - style="color:#000000;overflow:visible;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="M 133.73205,-94.726837 C 122.79246,-109.93118 111.85288,-125.13553 100.91329,-140.33988 67.27492,-93.55992 33.63655,-46.77996 -0.00182072,0 -0.00121381,-115.89147 -6.0690667e-4,-231.78295 0,-347.67442 c 55.211897,76.78306 110.42379,153.56611 165.63569,230.34917 -10.63455,7.5328 -21.26909,15.06561 -31.90364,22.598413 z" - id="path1641" /> - <path - style="color:#000000;overflow:visible;fill:#96caf3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="m 40,-106.7907 c 0,-39.4031 0,-78.8062 0,-118.2093 14.188768,19.70223 28.377535,39.40446 42.566303,59.10669 C 68.377535,-146.19244 54.188768,-126.49157 40,-106.7907 Z" - id="path1643" /> - <path - style="color:#000000;overflow:visible;opacity:1;fill:#530900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.803;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2;stroke-dasharray:none;stroke-opacity:0.5;paint-order:stroke markers fill" - d="M 4.9025e-5,-400 C 41.666699,-400 83.33335,-400 125,-400 c -21.86468,-7.42574 -43.729357,-14.85148 -65.594035,-22.27722" - id="path1955" /> - </g> - </g> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/bazzite-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/bazzite-logo.svg deleted file mode 100755 index f8726800..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/bazzite-logo.svg +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="496" height="496" viewBox="0 0 496 496" version="1.1"> -<defs> -<linearGradient id="linear0" gradientUnits="userSpaceOnUse" x1="50" y1="50" x2="550" y2="550" gradientTransform="matrix(0.918519,0,0,0.918519,-27.555556,-27.555556)"> -<stop offset="0.0684898" style="stop-color:rgb(0%,27.843139%,67.058825%);stop-opacity:1;"/> -<stop offset="0.741212" style="stop-color:rgb(54.11765%,16.862746%,88.627452%);stop-opacity:1;"/> -</linearGradient> -</defs> -<g id="surface1"> -<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear0);" d="M 18.371094 110.222656 C 18.371094 59.492188 59.492188 18.371094 110.222656 18.371094 L 248 18.371094 C 374.820312 18.371094 477.628906 121.179688 477.628906 248 C 477.628906 374.820312 374.820312 477.628906 248 477.628906 C 121.179688 477.628906 18.371094 374.820312 18.371094 248 Z M 18.371094 110.222656 "/> -<path style=" stroke:none;fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:0.501961;" d="M 135.941406 18.371094 L 194.726562 18.371094 L 194.726562 135.941406 L 317.976562 135.941406 C 369.625 135.941406 411.496094 177.808594 411.496094 229.460938 C 411.496094 329.996094 329.996094 411.496094 229.460938 411.496094 C 177.808594 411.496094 135.941406 369.625 135.941406 317.976562 L 135.941406 194.726562 L 18.371094 194.726562 L 18.371094 135.941406 L 135.941406 135.941406 Z M 194.726562 194.726562 L 194.726562 317.976562 C 194.726562 337.160156 210.277344 352.710938 229.460938 352.710938 C 297.527344 352.710938 352.710938 297.527344 352.710938 229.460938 C 352.710938 210.277344 337.160156 194.726562 317.976562 194.726562 Z M 194.726562 194.726562 "/> -<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:0.698039;" d="M 194.726562 73.480469 C 194.726562 58.261719 182.390625 45.925781 167.171875 45.925781 L 163.496094 45.925781 C 148.277344 45.925781 135.941406 58.261719 135.941406 73.480469 L 135.941406 135.941406 L 73.480469 135.941406 C 58.261719 135.941406 45.925781 148.277344 45.925781 163.496094 L 45.925781 167.171875 C 45.925781 182.390625 58.261719 194.726562 73.480469 194.726562 L 135.941406 194.726562 L 135.941406 257.183594 C 135.941406 272.402344 148.277344 284.742188 163.496094 284.742188 L 167.171875 284.742188 C 182.390625 284.742188 194.726562 272.402344 194.726562 257.183594 L 194.726562 194.726562 L 257.183594 194.726562 C 272.402344 194.726562 284.742188 182.390625 284.742188 167.171875 L 284.742188 163.496094 C 284.742188 148.277344 272.402344 135.941406 257.183594 135.941406 L 194.726562 135.941406 Z M 194.726562 73.480469 "/> -<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 259.480469 161.355469 C 262.542969 163.125 262.542969 167.542969 259.480469 169.308594 L 240.191406 180.445312 C 237.132812 182.214844 233.304688 180.003906 233.304688 176.46875 L 233.304688 154.195312 C 233.304688 150.660156 237.132812 148.453125 240.191406 150.21875 Z M 259.480469 161.355469 "/> -<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 169.308594 259.480469 C 167.542969 262.542969 163.125 262.542969 161.355469 259.480469 L 150.21875 240.191406 C 148.453125 237.132812 150.660156 233.304688 154.195312 233.304688 L 176.46875 233.304688 C 180.003906 233.304688 182.214844 237.132812 180.445312 240.191406 Z M 169.308594 259.480469 "/> -<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 161.355469 71.183594 C 163.125 68.125 167.542969 68.125 169.308594 71.183594 L 180.445312 90.472656 C 182.214844 93.535156 180.003906 97.363281 176.46875 97.363281 L 154.195312 97.363281 C 150.660156 97.363281 148.453125 93.535156 150.21875 90.472656 Z M 161.355469 71.183594 "/> -<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 71.183594 169.308594 C 68.125 167.542969 68.125 163.125 71.183594 161.355469 L 90.472656 150.21875 C 93.535156 148.453125 97.363281 150.660156 97.363281 154.195312 L 97.363281 176.46875 C 97.363281 180.003906 93.535156 182.214844 90.472656 180.445312 Z M 71.183594 169.308594 "/> -</g> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/budgie-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/budgie-logo-symbolic.svg deleted file mode 100755 index b216fc78..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/budgie-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - width="496" - height="496" - version="1.1" - id="svg16" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:dc="http://purl.org/dc/elements/1.1/"> - <metadata - id="metadata22"> - <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> - <defs - id="defs20" /> - <path - style="fill:#cccccc;stroke-width:11.57627106" - d="M 249.52542,16.949153 A 231.52542,231.52542 0 0 0 18,248.47458 231.52542,231.52542 0 0 0 249.52542,480 231.52542,231.52542 0 0 0 481.05085,248.47458 231.52542,231.52542 0 0 0 249.52542,16.949153 Z m 48.29476,46.305085 c 4.36594,-0.05788 8.54834,0.260466 13.27201,0.655217 25.83141,2.161984 53.25158,18.874647 71.15338,45.061565 24.14967,35.32626 22.98443,80.3693 0.81392,107.32916 -11.13767,13.54389 -14.72405,14.54779 -22.22551,20.59766 4.71798,-9.04894 6.11929,-12.51974 5.53943,-19.64806 -0.365,-4.47168 -2.06473,-8.02293 -3.02973,-10.01613 -3.70735,-7.65736 -9.41584,-10.5189 -16.09825,-13.81466 -8.21369,-4.051 -17.39067,-4.74836 -23.08471,-4.27327 -4.41592,0.36813 -6.69499,0.55451 -12.39023,2.50974 -26.98011,9.26322 -57.90528,0.80687 -74.45442,-23.40132 -19.78339,-28.93917 -12.00129,-69.01402 17.43224,-89.512588 8.66928,-6.037488 18.9172,-12.00031 28.7598,-13.950333 5.40898,-1.071962 9.94613,-1.479331 14.31207,-1.537444 z M 141.4953,144.31071 c 4.34856,-0.0926 8.66651,0.20027 12.91025,0.92726 17.05544,2.91896 19.66139,5.52315 28.53371,8.99881 -10.04346,0.39128 -13.68789,0.88212 -19.46714,4.88368 -3.62492,2.51113 -5.81414,5.6975 -7.03168,7.50652 -4.67743,6.94959 -4.26467,13.27903 -3.75323,20.64281 0.6287,9.05125 4.59266,17.27041 7.82302,21.93159 2.50524,3.61504 3.8069,5.47083 8.29784,9.40572 21.26964,18.63629 29.38003,49.39989 17.00265,75.51711 v 0.0232 c -14.81831,31.21329 -52.76068,44.21193 -84.80976,28.9859 -9.441374,-4.48616 -19.592241,-10.3823 -26.13705,-17.885 C 67.670676,297.00207 64.409456,290.49239 60.393571,281.98267 49.413134,258.71506 50.065068,226.94445 63.468519,198.68781 79.289715,165.33426 111.05539,144.98422 141.4953,144.31094 Z m 186.16995,138.91525 c 31.29817,0.7131 57.69741,25.34208 60.32324,57.70054 0.8248,10.16605 0.78591,21.62679 -2.39666,30.81731 -3.49806,10.1011 -7.43853,16.03718 -12.72938,23.58213 -14.46642,20.62961 -41.95319,35.59264 -72.71345,38.05248 -41.4958,3.31822 -78.76821,-19.28283 -90.55267,-50.80455 -5.92014,-15.83541 -4.9688,-19.27333 -6.37599,-28.46582 5.28917,8.29579 7.49874,11.10952 13.76943,14.04074 3.93435,1.83797 7.73396,2.13733 9.88053,2.28366 8.24667,0.56144 13.47177,-2.87138 19.51235,-6.8961 7.4248,-4.94689 12.51028,-12.31554 14.89992,-17.31915 1.85327,-3.88048 2.78715,-5.88445 3.93413,-11.59884 5.43352,-27.071 27.70446,-48.96022 56.14039,-51.23415 v 0.0231 c 2.12458,-0.17017 4.22161,-0.22805 6.30816,-0.18059 z" - id="circle4" /> -</svg> diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/clear-linux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/clear-linux-logo.svg deleted file mode 100755 index 1239cbdd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/clear-linux-logo.svg +++ /dev/null @@ -1,293 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg - viewBox="0 0 496.00001 496.00001" - version="1.1" - id="svg16" - sodipodi:docname="clear-linux-logo.svg" - width="496" - height="496" - inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" - inkscape:dataloss="true" - inkscape:export-filename="clear-linux-logo.svg" - inkscape:export-xdpi="96" - inkscape:export-ydpi="96" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns="http://www.w3.org/2000/svg" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:dc="http://purl.org/dc/elements/1.1/"> - <sodipodi:namedview - id="namedview16" - pagecolor="#ffffff" - bordercolor="#000000" - borderopacity="0.25" - inkscape:showpageshadow="2" - inkscape:pageopacity="0.0" - inkscape:pagecheckerboard="0" - inkscape:deskcolor="#d1d1d1" - inkscape:zoom="1.3045867" - inkscape:cx="176.30105" - inkscape:cy="234.55705" - inkscape:window-width="1920" - inkscape:window-height="1048" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:current-layer="svg16" /> - <defs - id="defs16"> - <style - id="style1">.cls-1{fill:url(#linear-gradient);}.cls-2{fill:url(#linear-gradient-2);}.cls-3{fill:url(#linear-gradient-3);}.cls-4{fill:url(#linear-gradient-4);}.cls-5{fill:#0070c5;}.cls-6{fill:url(#linear-gradient-5);}.cls-7{fill:url(#linear-gradient-6);}.cls-8{fill:url(#linear-gradient-7);}.cls-9{fill:url(#linear-gradient-8);}.cls-10{fill:url(#linear-gradient-9);}</style> - <linearGradient - id="linear-gradient" - x1="-727.56" - y1="-85.849998" - x2="-728.04999" - y2="-85.800003" - gradientTransform="matrix(20.22,0,0,47.23,14733.51,4089.2)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - stop-color="#7dd2f7" - id="stop1" /> - <stop - offset="1" - stop-color="#b1e4fa" - id="stop2" /> - </linearGradient> - <linearGradient - id="linear-gradient-2" - x1="-739.45001" - y1="-52.959999" - x2="-738.44" - y2="-52.279999" - gradientTransform="matrix(30.5,0,0,16.66,22572.77,885.64)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - stop-color="#33bef2" - id="stop3" /> - <stop - offset="0.75" - stop-color="#88e1b8" - id="stop4" /> - </linearGradient> - <linearGradient - id="linear-gradient-3" - x1="-714.38" - y1="-32.720001" - x2="-714.13" - y2="-32.470001" - gradientTransform="matrix(14.33,0,0,11.99,10248.5,397.99)" - xlink:href="#linear-gradient" /> - <linearGradient - id="linear-gradient-4" - x1="-729.33002" - y1="1.21" - x2="-728.5" - y2="2.72" - gradientTransform="matrix(20.88,0,0,8.09,15237.47,-3.56)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - stop-color="#33bef2" - id="stop5" /> - <stop - offset="0.85" - stop-color="#88e1b8" - id="stop6" /> - </linearGradient> - <linearGradient - id="linear-gradient-5" - x1="-735.59003" - y1="-87.980003" - x2="-735.96002" - y2="-87.43" - gradientTransform="matrix(26.53,0,0,53.4,19531.2,4732.97)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - stop-color="#00aeff" - id="stop7" /> - <stop - offset="1" - stop-color="#88e1b8" - id="stop8" /> - </linearGradient> - <linearGradient - id="linear-gradient-6" - x1="-739.40997" - y1="-23.92" - x2="-739.40997" - y2="-23.200001" - gradientTransform="matrix(31.1,0,0,10.63,23011.22,315.2)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - stop-color="#d1d3d5" - id="stop9" /> - <stop - offset="1" - stop-color="#f6f7f8" - id="stop10" /> - </linearGradient> - <linearGradient - id="linear-gradient-7" - x1="-736.17999" - y1="-56.27" - x2="-735.29999" - y2="-57.07" - gradientTransform="matrix(26.53,0,0,18.16,19531.2,1089.37)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0" - stop-color="#f6f7f8" - stop-opacity="0.4" - id="stop11" /> - <stop - offset="1" - stop-color="#f0f2f4" - stop-opacity="0" - id="stop12" /> - </linearGradient> - <linearGradient - id="linear-gradient-8" - x1="-739.40997" - y1="-20.59" - x2="-739.40997" - y2="-20.049999" - gradientTransform="matrix(31.1,0,0,10.21,23011.22,277.76)" - xlink:href="#linear-gradient-6" /> - <linearGradient - id="linear-gradient-9" - x1="-731.44" - y1="-89.099998" - x2="-729.95001" - y2="-88.629997" - gradientTransform="matrix(21.89,0,0,56.51,16019.62,5058.67)" - gradientUnits="userSpaceOnUse"> - <stop - offset="0.08" - stop-color="#fdb814" - id="stop13" /> - <stop - offset="0.35" - stop-color="#ffe966" - id="stop14" /> - <stop - offset="0.75" - stop-color="#f6f7f8" - id="stop15" /> - <stop - offset="1" - stop-color="#f0f2f4" - id="stop16" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - xlink:href="#linear-gradient" - id="linearGradient16" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(20.22,0,0,47.23,14733.51,4089.2)" - x1="-727.56" - y1="-85.849998" - x2="-728.04999" - y2="-85.800003" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linear-gradient-6" - id="linearGradient17" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(31.1,0,0,10.63,23011.22,315.2)" - x1="-739.40997" - y1="-23.92" - x2="-739.40997" - y2="-23.200001" /> - </defs> - <title - id="title16">Asset 1 - - - - - - - - - - - - - - - - - - - - Asset 1 - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/debian-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/debian-logo-symbolic.svg deleted file mode 100755 index 9ec90d39..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/debian-logo-symbolic.svg +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/debian-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/debian-logo.svg deleted file mode 100755 index a7a4fffa..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/debian-logo.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/endeavouros_logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/endeavouros_logo-symbolic.svg deleted file mode 100755 index 9f1b4b10..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/endeavouros_logo-symbolic.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/endeavouros_logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/endeavouros_logo.svg deleted file mode 100755 index 70480f37..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/endeavouros_logo.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/fedora-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/fedora-logo-symbolic.svg deleted file mode 100755 index cfbd3d9e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/fedora-logo-symbolic.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/fedora-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/fedora-logo.svg deleted file mode 100755 index ed1192dd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/fedora-logo.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/freebsd-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/freebsd-logo-symbolic.svg deleted file mode 100755 index 151e8826..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/freebsd-logo-symbolic.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/freebsd-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/freebsd-logo.svg deleted file mode 100755 index 4edfc039..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/freebsd-logo.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/garuda-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/garuda-logo-symbolic.svg deleted file mode 100755 index 62c9e069..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/garuda-logo-symbolic.svg +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gentoo-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gentoo-logo-symbolic.svg deleted file mode 100755 index 41a80cf9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gentoo-logo-symbolic.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gentoo-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gentoo-logo.svg deleted file mode 100755 index 13b36601..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gentoo-logo.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gnome-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gnome-logo.svg deleted file mode 100755 index 2939e06a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/gnome-logo.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/almalinux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/almalinux-logo-symbolic.svg deleted file mode 100755 index 57c97aa6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/almalinux-logo-symbolic.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/almalinux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/almalinux-logo.svg deleted file mode 100755 index de1a0364..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/almalinux-logo.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/arch-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/arch-logo-symbolic.svg deleted file mode 100755 index e1b12331..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/arch-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/arch-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/arch-logo.svg deleted file mode 100755 index 3a35f646..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/arch-logo.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/asahilinux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/asahilinux-logo-symbolic.svg deleted file mode 100755 index 58f25e1b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/asahilinux-logo-symbolic.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/asahilinux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/asahilinux-logo.svg deleted file mode 100755 index 42cf7f6b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/asahilinux-logo.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/budgie-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/budgie-logo-symbolic.svg deleted file mode 100755 index b216fc78..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/budgie-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/clear-linux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/clear-linux-logo.svg deleted file mode 100755 index 1239cbdd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/clear-linux-logo.svg +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Asset 1 - - - - - - - - - - - - - - - - - - - - Asset 1 - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/debian-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/debian-logo-symbolic.svg deleted file mode 100755 index 9ec90d39..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/debian-logo-symbolic.svg +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/debian-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/debian-logo.svg deleted file mode 100755 index a7a4fffa..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/debian-logo.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/endeavouros_logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/endeavouros_logo-symbolic.svg deleted file mode 100755 index 9f1b4b10..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/endeavouros_logo-symbolic.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/endeavouros_logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/endeavouros_logo.svg deleted file mode 100755 index 70480f37..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/endeavouros_logo.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/fedora-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/fedora-logo-symbolic.svg deleted file mode 100755 index cfbd3d9e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/fedora-logo-symbolic.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/fedora-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/fedora-logo.svg deleted file mode 100755 index ed1192dd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/fedora-logo.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/freebsd-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/freebsd-logo-symbolic.svg deleted file mode 100755 index 151e8826..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/freebsd-logo-symbolic.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/freebsd-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/freebsd-logo.svg deleted file mode 100755 index 4edfc039..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/freebsd-logo.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/garuda-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/garuda-logo-symbolic.svg deleted file mode 100755 index 62c9e069..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/garuda-logo-symbolic.svg +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gentoo-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gentoo-logo-symbolic.svg deleted file mode 100755 index 41a80cf9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gentoo-logo-symbolic.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gentoo-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gentoo-logo.svg deleted file mode 100755 index 13b36601..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gentoo-logo.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gnome-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gnome-logo.svg deleted file mode 100755 index 2939e06a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/gnome-logo.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/kali-linux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/kali-linux-logo-symbolic.svg deleted file mode 100755 index 3e396a8d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/kali-linux-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/kali-linux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/kali-linux-logo.svg deleted file mode 100755 index db19fd72..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/kali-linux-logo.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/manjaro-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/manjaro-logo-symbolic.svg deleted file mode 100755 index c6bf22c2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/manjaro-logo-symbolic.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/manjaro-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/manjaro-logo.svg deleted file mode 100755 index ea721c4e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/manjaro-logo.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/mx-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/mx-logo-symbolic.svg deleted file mode 100755 index 36234432..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/mx-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/netbsd-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/netbsd-logo.svg deleted file mode 100755 index 1a7d30b8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/netbsd-logo.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nixos-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nixos-logo-symbolic.svg deleted file mode 100755 index 7bb42edd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nixos-logo-symbolic.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nixos-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nixos-logo.svg deleted file mode 100755 index 1a756edb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nixos-logo.svg +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nobara-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nobara-logo-symbolic.svg deleted file mode 100755 index 2bdb4aad..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/nobara-logo-symbolic.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/openbsd-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/openbsd-logo.svg deleted file mode 100755 index a4309f2d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/openbsd-logo.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/opensuse-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/opensuse-logo-symbolic.svg deleted file mode 100755 index 4fc074c3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/opensuse-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/opensuse-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/opensuse-logo.svg deleted file mode 100755 index eaeaf0a1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/opensuse-logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - image/svg+xml - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pop-os-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pop-os-logo-symbolic.svg deleted file mode 100755 index 92dd61a7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pop-os-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pop-os-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pop-os-logo.svg deleted file mode 100755 index b3281542..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pop-os-logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - image/svg+xml - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pureos-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pureos-logo-symbolic.svg deleted file mode 100755 index 1160304d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/pureos-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/raspbian-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/raspbian-logo-symbolic.svg deleted file mode 100755 index 3a8f4404..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/raspbian-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/redhat-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/redhat-logo-symbolic.svg deleted file mode 100755 index 40727f45..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/redhat-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/redhat-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/redhat-logo.svg deleted file mode 100755 index 37d109b4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/redhat-logo.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/rockylinux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/rockylinux-logo-symbolic.svg deleted file mode 100755 index a4bf8237..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/rockylinux-logo-symbolic.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/rockylinux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/rockylinux-logo.svg deleted file mode 100755 index eb931889..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/rockylinux-logo.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/settings-logo-menu-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/settings-logo-menu-logo.svg deleted file mode 100755 index 8bdae617..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/settings-logo-menu-logo.svg +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/shastraos-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/shastraos-logo-symbolic.svg deleted file mode 100755 index 90e616c5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/shastraos-logo-symbolic.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/shastraos-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/shastraos-logo.svg deleted file mode 100755 index 9e400cd7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/shastraos-logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/solus-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/solus-logo-symbolic.svg deleted file mode 100755 index 6d61eb18..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/solus-logo-symbolic.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/solus-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/solus-logo.svg deleted file mode 100755 index eff40f3d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/solus-logo.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/tux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/tux-logo-symbolic.svg deleted file mode 100755 index ce309ca4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/tux-logo-symbolic.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/tux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/tux-logo.svg deleted file mode 100755 index 05b18116..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/tux-logo.svg +++ /dev/null @@ -1,55 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/ubuntu-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/ubuntu-logo-symbolic.svg deleted file mode 100755 index 3d80836a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/ubuntu-logo-symbolic.svg +++ /dev/null @@ -1,50 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/ubuntu-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/ubuntu-logo.svg deleted file mode 100755 index e886f744..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/ubuntu-logo.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/vanilla-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/vanilla-logo.svg deleted file mode 100755 index 74e3f2e3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/vanilla-logo.svg +++ /dev/null @@ -1,129 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/void-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/void-logo-symbolic.svg deleted file mode 100755 index 4e2b6bb4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/void-logo-symbolic.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/void-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/void-logo.svg deleted file mode 100755 index b3aa1e86..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/void-logo.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/voyager-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/voyager-logo-symbolic.svg deleted file mode 100755 index 4f869a7a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/voyager-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/zorin-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/zorin-logo-symbolic.svg deleted file mode 100755 index 5705d7ab..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/zorin-logo-symbolic.svg +++ /dev/null @@ -1,23 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/zorin-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/zorin-logo.svg deleted file mode 100755 index cc02a135..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/hicolor/16x16/actions/zorin-logo.svg +++ /dev/null @@ -1,23 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/kali-linux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/kali-linux-logo-symbolic.svg deleted file mode 100755 index 3e396a8d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/kali-linux-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/kali-linux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/kali-linux-logo.svg deleted file mode 100755 index db19fd72..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/kali-linux-logo.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/manjaro-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/manjaro-logo-symbolic.svg deleted file mode 100755 index c6bf22c2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/manjaro-logo-symbolic.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/manjaro-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/manjaro-logo.svg deleted file mode 100755 index 3c25addb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/manjaro-logo.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/mx-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/mx-logo-symbolic.svg deleted file mode 100755 index 36234432..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/mx-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/netbsd-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/netbsd-logo.svg deleted file mode 100755 index 1a7d30b8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/netbsd-logo.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nixos-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nixos-logo-symbolic.svg deleted file mode 100755 index 7bb42edd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nixos-logo-symbolic.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nixos-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nixos-logo.svg deleted file mode 100755 index 1a756edb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nixos-logo.svg +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nobara-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nobara-logo-symbolic.svg deleted file mode 100755 index 2bdb4aad..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/nobara-logo-symbolic.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/openbsd-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/openbsd-logo.svg deleted file mode 100755 index f4412118..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/openbsd-logo.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/opensuse-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/opensuse-logo-symbolic.svg deleted file mode 100755 index 4fc074c3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/opensuse-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/opensuse-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/opensuse-logo.svg deleted file mode 100755 index eaeaf0a1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/opensuse-logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - image/svg+xml - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pop-os-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pop-os-logo-symbolic.svg deleted file mode 100755 index 92dd61a7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pop-os-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pop-os-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pop-os-logo.svg deleted file mode 100755 index b3281542..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pop-os-logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - image/svg+xml - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pureos-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pureos-logo-symbolic.svg deleted file mode 100755 index 1160304d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/pureos-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/raspbian-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/raspbian-logo-symbolic.svg deleted file mode 100755 index 3a8f4404..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/raspbian-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/redhat-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/redhat-logo-symbolic.svg deleted file mode 100755 index 40727f45..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/redhat-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/redhat-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/redhat-logo.svg deleted file mode 100755 index 37d109b4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/redhat-logo.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/rockylinux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/rockylinux-logo-symbolic.svg deleted file mode 100755 index a4bf8237..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/rockylinux-logo-symbolic.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/rockylinux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/rockylinux-logo.svg deleted file mode 100755 index eb931889..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/rockylinux-logo.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/shastraos-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/shastraos-logo-symbolic.svg deleted file mode 100755 index 90e616c5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/shastraos-logo-symbolic.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/shastraos-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/shastraos-logo.svg deleted file mode 100755 index 9e400cd7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/shastraos-logo.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/solus-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/solus-logo-symbolic.svg deleted file mode 100755 index 6d61eb18..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/solus-logo-symbolic.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/solus-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/solus-logo.svg deleted file mode 100755 index eff40f3d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/solus-logo.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-le-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-le-logo.svg deleted file mode 100755 index d0f65ca9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-le-logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-logo-symbolic.svg deleted file mode 100755 index 19e37834..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-logo-symbolic.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-logo.svg deleted file mode 100755 index 223ac018..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/steam-deck-logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/tux-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/tux-logo-symbolic.svg deleted file mode 100755 index ce309ca4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/tux-logo-symbolic.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/tux-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/tux-logo.svg deleted file mode 100755 index 05b18116..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/tux-logo.svg +++ /dev/null @@ -1,55 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ublue-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ublue-logo-symbolic.svg deleted file mode 100755 index e14d0242..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ublue-logo-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ublue-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ublue-logo.svg deleted file mode 100755 index e24222b4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ublue-logo.svg +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ubuntu-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ubuntu-logo-symbolic.svg deleted file mode 100755 index 3d80836a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ubuntu-logo-symbolic.svg +++ /dev/null @@ -1,50 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ubuntu-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ubuntu-logo.svg deleted file mode 100755 index e886f744..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/ubuntu-logo.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/vanilla-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/vanilla-logo.svg deleted file mode 100755 index 74e3f2e3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/vanilla-logo.svg +++ /dev/null @@ -1,129 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/void-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/void-logo-symbolic.svg deleted file mode 100755 index 4e2b6bb4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/void-logo-symbolic.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/void-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/void-logo.svg deleted file mode 100755 index b3aa1e86..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/void-logo.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/voyager-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/voyager-logo-symbolic.svg deleted file mode 100755 index 4f869a7a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/voyager-logo-symbolic.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/zorin-logo-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/zorin-logo-symbolic.svg deleted file mode 100755 index 5705d7ab..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/zorin-logo-symbolic.svg +++ /dev/null @@ -1,23 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/zorin-logo.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/zorin-logo.svg deleted file mode 100755 index cc02a135..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/Resources/zorin-logo.svg +++ /dev/null @@ -1,23 +0,0 @@ - -image/svg+xml diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/constants.js b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/constants.js deleted file mode 100755 index 1f908a9a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/constants.js +++ /dev/null @@ -1,66 +0,0 @@ -export const SymbolicDistroIcons = [ - {PATH: 'start-here-symbolic'}, - {PATH: '/Resources/fedora-logo-symbolic.svg'}, - {PATH: '/Resources/debian-logo-symbolic.svg'}, - {PATH: '/Resources/manjaro-logo-symbolic.svg'}, - {PATH: '/Resources/pop-os-logo-symbolic.svg'}, - {PATH: '/Resources/ubuntu-logo-symbolic.svg'}, - {PATH: '/Resources/arch-logo-symbolic.svg'}, - {PATH: '/Resources/opensuse-logo-symbolic.svg'}, - {PATH: '/Resources/raspbian-logo-symbolic.svg'}, - {PATH: '/Resources/kali-linux-logo-symbolic.svg'}, - {PATH: '/Resources/pureos-logo-symbolic.svg'}, - {PATH: '/Resources/solus-logo-symbolic.svg'}, - {PATH: '/Resources/budgie-logo-symbolic.svg'}, - {PATH: '/Resources/gentoo-logo-symbolic.svg'}, - {PATH: '/Resources/mx-logo-symbolic.svg'}, - {PATH: '/Resources/redhat-logo-symbolic.svg'}, - {PATH: '/Resources/voyager-logo-symbolic.svg'}, - {PATH: '/Resources/garuda-logo-symbolic.svg'}, - {PATH: '/Resources/freebsd-logo-symbolic.svg'}, - {PATH: '/Resources/tux-logo-symbolic.svg'}, - {PATH: '/Resources/rockylinux-logo-symbolic.svg'}, - {PATH: '/Resources/endeavouros_logo-symbolic.svg'}, - {PATH: '/Resources/almalinux-logo-symbolic.svg'}, - {PATH: '/Resources/nixos-logo-symbolic.svg'}, - {PATH: '/Resources/shastraos-logo-symbolic.svg'}, - {PATH: '/Resources/asahilinux-logo-symbolic.svg'}, - {PATH: '/Resources/zorin-logo-symbolic.svg'}, - {PATH: '/Resources/void-logo-symbolic.svg'}, - {PATH: '/Resources/nobara-logo-symbolic.svg'}, - {PATH: '/Resources/steam-deck-logo-symbolic.svg'}, - {PATH: '/Resources/ublue-logo-symbolic.svg'}, -]; - -export const ColouredDistroIcons = [ - {PATH: '/Resources/fedora-logo.svg'}, - {PATH: '/Resources/debian-logo.svg'}, - {PATH: '/Resources/manjaro-logo.svg'}, - {PATH: '/Resources/pop-os-logo.svg'}, - {PATH: '/Resources/ubuntu-logo.svg'}, - {PATH: '/Resources/arch-logo.svg'}, - {PATH: '/Resources/opensuse-logo.svg'}, - {PATH: '/Resources/kali-linux-logo.svg'}, - {PATH: '/Resources/solus-logo.svg'}, - {PATH: '/Resources/gentoo-logo.svg'}, - {PATH: '/Resources/redhat-logo.svg'}, - {PATH: '/Resources/freebsd-logo.svg'}, - {PATH: '/Resources/openbsd-logo.svg'}, - {PATH: '/Resources/netbsd-logo.svg'}, - {PATH: '/Resources/tux-logo.svg'}, - {PATH: '/Resources/rockylinux-logo.svg'}, - {PATH: '/Resources/endeavouros_logo.svg'}, - {PATH: '/Resources/almalinux-logo.svg'}, - {PATH: '/Resources/nixos-logo.svg'}, - {PATH: '/Resources/shastraos-logo.svg'}, - {PATH: '/Resources/asahilinux-logo.svg'}, - {PATH: '/Resources/zorin-logo.svg'}, - {PATH: '/Resources/vanilla-logo.svg'}, - {PATH: '/Resources/gnome-logo.svg'}, - {PATH: '/Resources/clear-linux-logo.svg'}, - {PATH: '/Resources/void-logo.svg'}, - {PATH: '/Resources/steam-deck-logo.svg'}, - {PATH: '/Resources/steam-deck-le-logo.svg'}, - {PATH: '/Resources/bazzite-logo.svg'}, - {PATH: '/Resources/ublue-logo.svg'}, -]; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/display_module.js b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/display_module.js deleted file mode 100755 index 039c82e1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/display_module.js +++ /dev/null @@ -1,45 +0,0 @@ -/* -This file has been copied from EasyScreenCast/display_module.js [1], with no -edits. We primarily need the set_cursor method as it is used in selection.js - -[1]: https://github.com/EasyScreenCast/EasyScreenCast/blob/e3a359f/display_module.js -*/ - -'use strict'; - -/** - * @type {{_display(): Meta_Display, number_of_displays(): int}} - */ -export const DisplayApi = { - /** - * Returns the Wayland display or screen - * - * @returns {Meta.Display} - */ - _display() { - return global.display || global.screen; - }, - - /** - * @returns {int} - * @public - */ - number_displays() { - return this._display().get_n_monitors(); - }, - - /** - * @param {number} displayIndex the monitor number - * @returns {Meta.Rectangle} - */ - display_geometry_for_index(displayIndex) { - return this._display().get_monitor_geometry(displayIndex); - }, - - /** - * @param {Meta.Cursor} cursor the new cursor to set - */ - set_cursor(cursor) { - this._display().set_cursor(cursor); - }, -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/extension.js deleted file mode 100755 index 0d712d07..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/extension.js +++ /dev/null @@ -1,283 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as Util from 'resource:///org/gnome/shell/misc/util.js'; - -import * as Constants from './constants.js'; -import * as Selection from './selection.js'; - -import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -const MenuItem = GObject.registerClass( -class LogoMenuMenuItem extends PopupMenu.PopupMenuItem { - _init(name, activateFunction) { - super._init(name); - this.connect('activate', () => activateFunction()); - } -}); - -const MenuButton = GObject.registerClass( -class LogoMenuMenuButton extends PanelMenu.Button { - _init(extension) { - super._init(0.5, 'LogoMenu'); - this._extension = extension; - this._settings = extension.getSettings(); - - // Icon - this.icon = new St.Icon({ - style_class: 'menu-button', - }); - - this._settings.connectObject('changed::hide-icon-shadow', () => this.hideIconShadow(), this); - this._settings.connectObject('changed::menu-button-icon-image', () => this.setIconImage(), this); - this._settings.connectObject('changed::symbolic-icon', () => this.setIconImage(), this); - this._settings.connectObject('changed::use-custom-icon', () => this.setIconImage(), this); - this._settings.connectObject('changed::custom-icon-path', () => this.setIconImage(), this); - this._settings.connectObject('changed::menu-button-icon-size', () => this.setIconSize(), this); - - this.hideIconShadow(); - this.setIconImage(); - this.setIconSize(); - this.add_child(this.icon); - - // Menu - this._settings.connectObject('changed::hide-softwarecentre', () => this._displayMenuItems(), this); - this._settings.connectObject('changed::show-power-options', () => this._displayMenuItems(), this); - this._settings.connectObject('changed::hide-forcequit', () => this._displayMenuItems(), this); - this._settings.connectObject('changed::show-lockscreen', () => this._displayMenuItems(), this); - this._settings.connectObject('changed::show-activities-button', () => this._displayMenuItems(), this); - this._displayMenuItems(); - - // bind middle click option to toggle overview - this.connect('button-press-event', this._buttonPressEvent.bind(this)); - } - - _addItem(item) { - this.menu.addMenuItem(item); - } - - _displayMenuItems() { - const showPowerOptions = this._settings.get_boolean('show-power-options'); - const showForceQuit = !this._settings.get_boolean('hide-forcequit'); - const showLockScreen = this._settings.get_boolean('show-lockscreen'); - const showSoftwareCenter = !this._settings.get_boolean('hide-softwarecentre'); - const showActivitiesButton = this._settings.get_boolean('show-activities-button'); - - this.menu.removeAll(); - - this._addItem(new MenuItem(_('About My System'), () => this._aboutThisDistro())); - // this._addItem(new MenuItem(_('System Settings...'), () => this._systemPreferences())); - this._addItem(new PopupMenu.PopupSeparatorMenuItem()); - - if (!showActivitiesButton) - this._addItem(new MenuItem(_('Activities'), () => this._overviewToggle())); - - this._addItem(new MenuItem(_('App Grid'), () => this._showAppGrid())); - this._addItem(new PopupMenu.PopupSeparatorMenuItem()); - - if (showSoftwareCenter) - this._addItem(new MenuItem(_('Software Center...'), () => this._openSoftwareCenter())); - - this._addItem(new MenuItem(_('System Monitor'), () => this._openSystemMonitor())); - this._addItem(new MenuItem(_('Terminal'), () => this._openTerminal())); - this._addItem(new MenuItem(_('Extensions'), () => this._openExtensionsApp())); - - if (showForceQuit) { - this._addItem(new PopupMenu.PopupSeparatorMenuItem()); - this._addItem(new MenuItem(_('Force Quit App'), () => this._forceQuit())); - } - - if (showPowerOptions) { - this._addItem(new PopupMenu.PopupSeparatorMenuItem()); - this._addItem(new MenuItem(_('Sleep'), () => this._sleep())); - this._addItem(new MenuItem(_('Restart...'), () => this._restart())); - this._addItem(new MenuItem(_('Shut Down...'), () => this._shutdown())); - this._addItem(new PopupMenu.PopupSeparatorMenuItem()); - - if (showLockScreen) - this._addItem(new MenuItem(_('Lock Screen'), () => this._lockScreen())); - - this._addItem(new MenuItem(_('Log Out...'), () => this._logOut())); - } else if (!showPowerOptions && showLockScreen) { - this._addItem(new PopupMenu.PopupSeparatorMenuItem()); - this._addItem(new MenuItem(_('Lock Screen'), () => this._lockScreen())); - } - } - - _buttonPressEvent(actor, event) { - // left click === 1, middle click === 2, right click === 3 - const clickType = this._settings.get_int('menu-button-icon-click-type'); - if (event.get_button() === clickType) { - this.menu.close(); - Main.overview.toggle(); - } - } - - _aboutThisDistro() { - Util.spawn(['gnome-control-center', 'info-overview']); - } - - _systemPreferences() { - Util.spawn(['gnome-control-center']); - } - - _overviewToggle() { - Main.overview.toggle(); - } - - _sleep() { - Util.spawn(['systemctl', 'suspend']); - } - - _restart() { - Util.spawn(['gnome-session-quit', '--reboot']); - } - - _shutdown() { - Util.spawn(['gnome-session-quit', '--power-off']); - } - - _lockScreen() { - Util.spawn(['loginctl', 'lock-session']); - } - - _logOut() { - Util.spawn(['gnome-session-quit', '--logout']); - } - - _showAppGrid() { - // Code snippet from - https://github.com/G-dH/custom-hot-corners-extended/blob/gdh/actions.js - // Pressing the apps btn before overview activation avoids icons animation in GS 3.36/3.38 - Main.overview.dash.showAppsButton.checked = true; - // in 3.36 pressing the button is usualy enough to activate overview, but not always - Main.overview.show(); - // pressing apps btn before overview has no effect in GS 40, so once again - Main.overview.dash.showAppsButton.checked = true; - } - - _forceQuit() { - new Selection.SelectionWindow(); - } - - _openTerminal() { - Util.trySpawnCommandLine(this._settings.get_string('menu-button-terminal')); - } - - _openSoftwareCenter() { - Util.trySpawnCommandLine(this._settings.get_string('menu-button-software-center')); - } - - _openSystemMonitor() { - Util.trySpawnCommandLine(this._settings.get_string('menu-button-system-monitor')); - } - - _openExtensionsApp() { - const appSys = Shell.AppSystem.get_default(); - const extensionManagerChoice = this._settings.get_string('menu-button-extensions-app'); - const extensionApp = appSys.lookup_app(extensionManagerChoice); - if (extensionApp) { - try { - extensionApp.launch( - 0, - -1, - Shell.AppLaunchGpu.APP_PREF - ); - } catch (e) { - log(e); - } - } - } - - setIconImage() { - const iconIndex = this._settings.get_int('menu-button-icon-image'); - const isSymbolic = this._settings.get_boolean('symbolic-icon'); - const useCustomIcon = this._settings.get_boolean('use-custom-icon'); - const customIconPath = this._settings.get_string('custom-icon-path'); - let isStartHereSymbolic = false; - let iconPath; - let notFound = false; - - if (useCustomIcon && customIconPath !== '') { - iconPath = customIconPath; - } else if (isSymbolic) { - if (Constants.SymbolicDistroIcons[iconIndex] !== undefined) { - isStartHereSymbolic = Constants.SymbolicDistroIcons[iconIndex].PATH === 'start-here-symbolic'; - iconPath = this._extension.path + Constants.SymbolicDistroIcons[iconIndex].PATH; - } else { - notFound = true; - } - } else { - if (Constants.ColouredDistroIcons[iconIndex] !== undefined) { - iconPath = this._extension.path + Constants.ColouredDistroIcons[iconIndex].PATH; - } else { - notFound = true; - } - } - - if (notFound) { - iconPath = 'start-here-symbolic'; - this._settings.set_boolean('symbolic-icon', true); - this._settings.set_int('menu-button-icon-image', 0); - } - - const fileExists = GLib.file_test(iconPath, GLib.FileTest.IS_REGULAR); - - const icon = isStartHereSymbolic || !fileExists ? 'start-here-symbolic' : iconPath; - - this.icon.gicon = Gio.icon_new_for_string(icon); - } - setIconSize() { - const iconSize = this._settings.get_int('menu-button-icon-size'); - this.icon.icon_size = iconSize; - } - - hideIconShadow() { - const iconShadow = this._settings.get_boolean('hide-icon-shadow'); - - if(!iconShadow){ - this.icon.add_style_class_name('system-status-icon'); - } else { - this.icon.remove_style_class_name('system-status-icon'); - } - } -}); - -export default class LogoMenu extends Extension { - enable() { - this.settings = this.getSettings(); - - this.settings.connectObject('changed::show-activities-button', - () => this._setActivitiesVisibility(), this); - - this._setActivitiesVisibility(); - - const indicator = new MenuButton(this); - Main.panel.addToStatusArea('LogoMenu', indicator, 0, 'left'); - } - - disable() { - if (!Main.sessionMode.isLocked) - Main.panel.statusArea.activities?.container.show(); - - Main.panel.statusArea['LogoMenu'].destroy(); - } - - _setActivitiesVisibility() { - const showActivitiesButton = this.settings.get_boolean('show-activities-button'); - const activitiesButton = Main.panel.statusArea['activities']; - - if (!activitiesButton) - return; - - if (showActivitiesButton) - activitiesButton.container.show(); - else - activitiesButton.container.hide(); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/be/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/be/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index f0b3ccb3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/be/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ca/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ca/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index c19f3233..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ca/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/de/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/de/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index 5300cc19..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/de/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/es/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/es/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index acd86d0c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/es/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/fr/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/fr/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index d6cf579c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/fr/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/it/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/it/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index 47e012b8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/it/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ko/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ko/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index 68d9fc41..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ko/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/nl/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/nl/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index d6e80100..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/nl/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/pt_BR/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/pt_BR/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index 070ea3c9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/pt_BR/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ru/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ru/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index 35633528..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/ru/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/tr/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/tr/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index e06d659f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/tr/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/zh_CN/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/zh_CN/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index 40352150..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/zh_CN/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/zh_TW/LC_MESSAGES/logo-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/zh_TW/LC_MESSAGES/logo-menu.mo deleted file mode 100755 index b1baade7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/locale/zh_TW/LC_MESSAGES/logo-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/metadata.json deleted file mode 100755 index 24b8e09d..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Logo Menu - Menu similar to Apple's macOS menu for the GNOME Desktop\nThis extension gives a simple menu along with the ability to get the icon of your distro on top left part of the panel for a great look.\nThe Icon can be customised through settings, it has both Linux and BSD logos.\nFor more screenshots, visit GitHub.\n\nThe 'Activities' indicator is hidden by default but can be enabled through settings.\n\nThe default Terminal and Software centre can also be changed.\n\n Force Quit works on Wayland and Xorg", - "donations": { - "github": "aryan20" - }, - "gettext-domain": "logo-menu", - "name": "Logo Menu", - "settings-schema": "org.gnome.shell.extensions.logo-menu", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/Aryan20/Logomenu", - "uuid": "logomenu@aryan_k", - "version": 30, - "version-name": "22.6" -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/prefs.js deleted file mode 100755 index 33505479..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/prefs.js +++ /dev/null @@ -1,26 +0,0 @@ -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; - -import {AboutPage, LogoMenuIconsPage, LogoMenuOptionsPage} from './PrefsLib/adw.js'; - -import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class LogoMenuPrefs extends ExtensionPreferences { - fillPreferencesWindow(window) { - window.search_enabled = true; - - const settings = this.getSettings(); - - const iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - if (!iconTheme.get_search_path().includes(`${this.path}/Resources`)) - iconTheme.add_search_path(`${this.path}/Resources`); - - const iconSettingsPage = new LogoMenuIconsPage(settings); - window.add(iconSettingsPage); - const optionsPage = new LogoMenuOptionsPage(settings); - window.add(optionsPage); - const aboutPage = new AboutPage(this.metadata); - window.add(aboutPage); - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/schemas/gschemas.compiled deleted file mode 100755 index cab2a6e8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/schemas/org.gnome.shell.extensions.logo-menu.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/schemas/org.gnome.shell.extensions.logo-menu.gschema.xml deleted file mode 100755 index 6c6fa1e8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/schemas/org.gnome.shell.extensions.logo-menu.gschema.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - 0 - Menu Button Icon Image - Change the Menu Button Icon Image. - - - - 25 - Menu Button Icon Size - Change the Menu Button Icon Size. - - - - 2 - Menu Button click type to open Activity - Change the Menu Button click type to open Activity. - - - - "org.gnome.Extensions.desktop" - Preffered Extensions app - Change to preffered Extensions app. - - - - "gnome-software" - Menu Button Software Center - Change the Menu Button Software Center. - - - - "gnome-terminal" - Menu Button Terminal - Change the Menu Button Terminal. - - - - false - Toggle power options visibility - Toggle power options visibility. - - - - false - Use Custom Icon - Whether to use a custom icon or not. - - - - "''" - Custom Icon Path - Path to the custom icon image file. - - - - false - Toggle Force Quit option visibility - Toggle Force Quit option visibility. - - - - false - Toggle Lock screen option visibility - Toggle Force Quit option visibility. - - - - false - Toggle Software Centre option visibility - Toggle Software Centre option visibility. - - - - false - Toggle visibility of the top panel activities button - Toggle visibility of the top panel activities button. - - - - false - Toggle visibility of the top panel icon's shadow - Toggle visibility of the top panel icon's shadow. - - - - - true - Toggle if user chose symbolic or coloured distro logo - Toggle if user chose symbolic or coloured distro logo. - - - - "gnome-system-monitor" - Menu System Monitor - Change the Menu System Monitor. - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/selection.js b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/selection.js deleted file mode 100755 index d9b1f954..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/selection.js +++ /dev/null @@ -1,197 +0,0 @@ -/* -The MIT License (MIT) -Copyright (c) 2023 Aryan20 -Copyright (c) 2013 otto.allmendinger@gmail.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* - -This file has been copied from force-quit/selection.js [1], with edits. -Edits primarily involves removing graphical feedback and logging. - -[1]: https://github.com/meghprkh/force-quit/blob/master/selection.js -*/ - -'use strict'; - -import GObject from 'gi://GObject'; -import Meta from 'gi://Meta'; -import Clutter from 'gi://Clutter'; -import St from 'gi://St'; - -import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; - -import {DisplayApi} from './display_module.js'; - -class Capture extends Signals.EventEmitter { - /** - * @private - */ - constructor() { - super(); - - this._mouseDown = false; - - this.monitor = Main.layoutManager.focusMonitor; - - this._areaSelection = new St.Widget({ - name: 'area-selection', - style_class: 'area-selection', - visible: 'true', - reactive: 'true', - x: -10, - y: -10, - }); - - Main.uiGroup.add_actor(this._areaSelection); - - this._grab = Main.pushModal(this._areaSelection); - - if (this._grab) { - this._signalCapturedEvent = this._areaSelection.connect( - 'captured-event', - this._onCaptureEvent.bind(this) - ); - - this._setCaptureCursor(); - } - } - - /** - * @private - */ - _setDefaultCursor() { - DisplayApi.set_cursor(Meta.Cursor.DEFAULT); - } - - /** - * @private - */ - _setCaptureCursor() { - DisplayApi.set_cursor(Meta.Cursor.CROSSHAIR); - } - - /** - * @param {Clutter.Actor} actor the actor that received the event - * @param {Clutter.Event} event a Clutter.Event - * @private - */ - _onCaptureEvent(actor, event) { - if (event.type() === Clutter.EventType.KEY_PRESS) { - if (event.get_key_symbol() === Clutter.KEY_Escape) { - this._stop(); - } - } - - this.emit('captured-event', event); - } - - /** - * @private - */ - _stop() { - global.stage.disconnect(this._signalCapturedEvent); - this._setDefaultCursor(); - Main.uiGroup.remove_actor(this._areaSelection); - Main.popModal(this._grab); - this._areaSelection.destroy(); - this.emit('stop'); - this.disconnectAll(); - } - - toString() { - return this.GTypeName; - } -} - -export class SelectionWindow extends Signals.EventEmitter { - /** - * @private - */ - constructor() { - super() - - this._windows = global.get_window_actors(); - this._capture = new Capture(); - this._capture.connect('captured-event', this._onEvent.bind(this)); - this._capture.connect('stop', this.emit.bind(this, 'stop')); - } - - /** - * @param {Clutter.Actor} capture the actor the captured the event - * @param {Clutter.Event} event a Clutter.Event - * @private - */ - _onEvent(capture, event) { - let type = event.type(); - let [x, y] = global.get_pointer(); - - this._selectedWindow = _selectWindow(this._windows, x, y); - - if (type === Clutter.EventType.BUTTON_PRESS) { - if (event.get_button() === Clutter.BUTTON_SECONDARY) { - this._capture._stop(); - } else if (this._selectedWindow) { - this._capture._stop(); - - this._selectedWindow.get_meta_window().kill() - } - } - } - - toString() { - return this.GTypeName; - } -} - -/** - * @param {Array(Clutter.Actor)} windows all windows on the display - * @param {number} x left position - * @param {number} y top position - * @returns {Clutter.Actor} - */ -function _selectWindow(windows, x, y) { - let filtered = windows.filter(win => { - if ( - win !== undefined && - win.visible && - typeof win.get_meta_window === 'function' - ) { - - let [w, h] = win.get_size(); - let [wx, wy] = win.get_position(); - - return wx <= x && wy <= y && wx + w >= x && wy + h >= y; - } else { - return false; - } - }); - - filtered.sort((a, b) => { - return ( - a.get_meta_window().get_layer() <= b.get_meta_window().get_layer() - ); - }); - - return filtered[0]; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/stylesheet.css deleted file mode 100755 index f1b33be5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/logomenu@aryan_k/stylesheet.css +++ /dev/null @@ -1,9 +0,0 @@ -.menu-button { - margin: 1px !important; - padding: 0px !important; -} - -.menu-button-hover { - margin: 1px !important; - padding: 0px !important; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/LICENSE b/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/LICENSE deleted file mode 100755 index 3287eb97..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Krypion17 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/extension.js deleted file mode 100755 index e0d27f7e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/extension.js +++ /dev/null @@ -1,20 +0,0 @@ -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import { ProgressBarManager as ProgressBarManager, ProgressBar as ProgressBar } from "./progressBar.js"; -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -export default class mediaProgress extends Extension { - constructor(metadata) { - super(metadata); - } - - enable() { - this.media_section = Main.panel.statusArea.dateMenu._messageList._mediaSection; - this.progressBarManager = new ProgressBarManager(this.media_section); - } - - disable() { - this.progressBarManager?.destroy(); - this.progressBarManager = null; - this.media_section = null; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/metadata.json deleted file mode 100755 index d02c5173..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Progress Bar for the GNOME Media Notification", - "name": "Media Progress", - "shell-version": [ - "46" - ], - "url": "https://github.com/Krypion17/media-progress", - "uuid": "media-progress@krypion17", - "version": 13 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/progressBar.js b/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/progressBar.js deleted file mode 100755 index 313a38e4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/progressBar.js +++ /dev/null @@ -1,278 +0,0 @@ -import Gio from "gi://Gio"; -import GLib from "gi://GLib"; -import GObject from "gi://GObject"; -import St from 'gi://St'; - - -import {Slider} from 'resource:///org/gnome/shell/ui/slider.js'; - -import { loadInterfaceXML } from 'resource:///org/gnome/shell/misc/fileUtils.js'; - -let timeout; - -export class ProgressBarManager extends Slider { - _init(mediaSection) { - super._init(0); - - const DBusIface = loadInterfaceXML('org.freedesktop.DBus'); - const DBusProxy = Gio.DBusProxy.makeProxyWrapper(DBusIface); - - this._dbusProxy = new DBusProxy(Gio.DBus.session, - 'org.freedesktop.DBus', - '/org/freedesktop/DBus', - this._onProxyReady.bind(this)); - - - this._mediaSection = mediaSection; - - - this.signals = []; - this.bars = {}; - } - - _addProgress(name, owners, newOwner, oldOwner) { - for (let i of this._mediaSection._messages) { - if (i._player._busName === name) { - if (owners && !newOwner && oldOwner) - return; - - try { - if (i.get_child().get_last_child().get_child_at_index(1) instanceof ProgressBar) - return; - } catch { - return; - } - - let length; - - const MprisPlayerIface = loadInterfaceXML('org.mpris.MediaPlayer2.Player'); - const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface); - - let playerProxy = new MprisPlayerProxy(Gio.DBus.session, name, '/org/mpris/MediaPlayer2'); - - try { - length = playerProxy.get_connection().call_sync( - name, - "/org/mpris/MediaPlayer2", - "org.freedesktop.DBus.Properties", - "Get", - new GLib.Variant("(ss)", ["org.mpris.MediaPlayer2.Player", "Metadata"]), - null, - Gio.DBusCallFlags.NONE, - 50, - null - ).recursiveUnpack()[0]['mpris:length'] / 60000000; - if (!length) - return; - } catch (e) { - return; - } - - let timestamp1 = new St.Label({ - style_class: "progressbar-timestamp" - }); - timestamp1.set_text("0:00"); - - let timestamp2 = new St.Label({ - style_class: "progressbar-timestamp" - }); - - let progressBar = new ProgressBar(0, this, name, [timestamp1, timestamp2]); - let box = new St.BoxLayout(); - playerProxy = null; - timestamp2.set_text(`${Math.floor(length)}:${Math.floor((length - Math.floor(length))*60).toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping:false})}`); - box.add_child(timestamp1); - box.add_child(progressBar); - box.add_child(timestamp2); - i.get_child().add_child(box); - this.bars[name] = progressBar; - - this.signals.push(i._player.connect('closed', (() => { - if (timeout) - clearInterval(timeout); - if (!this.bars[name]) - return; - this.bars[name].destroy(); - delete this.bars[name]; - }))); - } - } - } - - async _onProxyReady() { - const [names] = await this._dbusProxy.ListNamesAsync().catch(); - names.forEach(name => { - if (!name.startsWith('org.mpris.MediaPlayer2.')) - return; - - this._addProgress(name, false); - }); - this.signals.push(this._dbusProxy.connectSignal("NameOwnerChanged", (pproxy, sender, [name, oldOwner, newOwner]) => { - if (!name.startsWith('org.mpris.MediaPlayer2.')) - return; - this.signals.push(this._mediaSection._players.get(name).connect('changed', () => { - this._addProgress(name, true, newOwner, oldOwner); - })); - - this.timeout = setTimeout(() => { - this._addProgress(name, true, newOwner, oldOwner); - }, 500); - })); - } - - destroy() { - clearTimeout(this.timeout); - - for (let i in this.bars) { - if (!this.bars[i]) - continue; - this.bars[i].destroy(); - delete this.bars[i]; - } - - this.signals.map((i) => { - this.disconnect(i); - }); - - for (let i of this._mediaSection._messages) { - try { - if (i.get_child().get_last_child().get_child_at_index(1) instanceof ProgressBar) - i.get_child().get_last_child().get_child_at_index(1).destroy(); - } catch {} - } - - super.destroy(); - } -} - -export class ProgressBar extends Slider { - _init(value, manager, busName, timestamps) { - super._init(value); - - this._busName = busName; - this.manager = manager; - this.timestamps = timestamps; - this._updateSettings(); - this.updateSignal = St.Settings.get().connect('notify', () => this._updateSettings()); - this.track_hover = true; - - this.signals = []; - - const MprisPlayerIface = loadInterfaceXML('org.mpris.MediaPlayer2.Player'); - const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface); - - this._playerProxy = MprisPlayerProxy(Gio.DBus.session, this._busName, '/org/mpris/MediaPlayer2', this._onPlayerProxyReady.bind(this)); - - const position = this.getProperty("Position"); - this.value = position / this._length; - - timeout = setInterval(() => { - if (this._dragging || this.getProperty("PlaybackStatus") !== "Playing") - return; - if (!this) { - clearInterval(timeout); - return; - } - let position = this.getProperty("Position"); - - this.value = position / this._length; - position = position / 60000000; - this.timestamps[0].set_text(`${Math.floor(position)}:${Math.floor((position - Math.floor(position))*60).toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping:false})}`); - }, 1000); - - this.signals.push(this.connect("drag-end", () => { - if (this._dragging) - return; - this.setPosition(this.value * this._length); - })); - } - - _updateInfo() { - this._trackId = this.getProperty("Metadata")['mpris:trackid']; - if (!this._trackId) - this.reactive = false; - if (this._trackId !== 0 && this.getProperty("CanSeek")) - this.reactive = true; - if (!this._length) - this._length = this.getProperty("Metadata")['mpris:length']; - if (!this._length) { - this.visible = false; - this.timestamps[0].visible = false; - this.timestamps[1].visible = false; - } - else { - this.visible = true; - this.timestamps[0].visible = true; - this.timestamps[1].visible = true; - } - this.timestamps[1].set_text(`${Math.floor(this._length / 60000000)}:${Math.floor((this._length / 60000000 - Math.floor(this._length / 60000000))*60).toLocaleString('en-US', {minimumIntegerDigits: 2, useGrouping:false})}`); - } - - getProperty(prop) { - try { - return this._playerProxy.get_connection().call_sync( - this._busName, - "/org/mpris/MediaPlayer2", - "org.freedesktop.DBus.Properties", - "Get", - new GLib.Variant("(ss)", ["org.mpris.MediaPlayer2.Player", prop]), - null, - Gio.DBusCallFlags.NONE, - 50, - null - ).recursiveUnpack()[0]; - } catch { - return 0; - } - } - - setPosition(value) { - this._playerProxy.get_connection().call_sync( - this._busName, - "/org/mpris/MediaPlayer2", - "org.mpris.MediaPlayer2.Player", - "SetPosition", - new GLib.Variant("(ox)", [this._trackId, value.toString()]), - null, - Gio.DBusCallFlags.NONE, - 50, - null - ); - } - - _onPlayerProxyReady() { - this.signals.push(this._playerProxy.connectObject('g-properties-changed', () => this._updateInfo(), this)); - this._updateInfo(); - } - - _updateSettings() { - if (St.Settings.get().color_scheme === 0 && GLib.get_os_info("NAME").includes("Ubuntu")) { - this.remove_style_class_name('progress-bar'); - this.add_style_class_name('progress-bar-light'); - } else if (St.Settings.get().color_scheme === 2) { - this.remove_style_class_name('progress-bar'); - this.add_style_class_name('progress-bar-light'); - } else { - this.remove_style_class_name('progress-bar-light'); - this.add_style_class_name('progress-bar'); - } - - } - - destroy() { - this.signals.map((i) => { - this.disconnect(i); - }); - St.Settings.get().disconnect(this.updateSignal); - clearInterval(timeout); - this._playerProxy = null; - this.timestamps[0].destroy(); - this.timestamps[1].destroy(); - if (this.manager.bars[this._busName]) - delete this.manager.bars[this._busName]; - super.destroy(); - } -} - -GObject.registerClass(ProgressBarManager); -GObject.registerClass(ProgressBar); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/stylesheet.css deleted file mode 100755 index 5a26838e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/media-progress@krypion17/stylesheet.css +++ /dev/null @@ -1,38 +0,0 @@ -/* Add your custom extension styling here */ - -.progress-bar { - -barlevel-height: 4px; - -slider-handle-radius: 0px; - -barlevel-active-background-color: white; - margin: 5px 5px 10px; - padding: 0; - color: white; -} - -.progress-bar-light { - -barlevel-height: 4px; - -slider-handle-radius: 0px; - -barlevel-active-background-color: #282828; - margin: 5px 5px 10px; - padding: 0; - color: #282828; -} - -.progress-bar-light:hover { - -slider-handle-radius: 5px; - -slider-handle-border-width: 0px; - height: 14px; - margin: 0 5px 5px; -} -.progress-bar:hover { - -slider-handle-radius: 5px; - -slider-handle-border-width: 0px; - height: 14px; - margin: 0 5px 5px; -} - -.progressbar-timestamp { - font-family: Noto Sans; - margin: 0 15px 10px; -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/extension.js deleted file mode 100755 index 2d804347..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/extension.js +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2024 kuvaus -// Licence: GPLv3 - -import Gio from 'gi://Gio'; -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -export default class MoveClockAndStatusMenu extends Extension { - _init() { - this._dateMenu = null; - this._statusMenu = null; - this._settings = this.getSettings(); - } - - enable() { - this._init(); - let centerBox = Main.panel._centerBox; - let rightBox = Main.panel._rightBox; - let dateMenu = Main.panel.statusArea['dateMenu']; - let statusMenu = Main.panel.statusArea['quickSettings']; - let children = centerBox.get_children(); - let clockBeforeStatusMenu = this._settings.get_boolean('clock-before-statusmenu'); - - // Store references to the dateMenu and statusMenu for later use - this._dateMenu = dateMenu; - this._statusMenu = statusMenu; - - // Move the dateMenu to the rightBox - if (children.indexOf(dateMenu.container) != -1) { - centerBox.remove_child(dateMenu.container); - // Move the dateMenu to the rightBox after statusMenu - if (!clockBeforeStatusMenu) { rightBox.add_child(dateMenu.container); } - // Move the dateMenu to the rightBox before statusMenu - else { rightBox.insert_child_at_index(dateMenu.container, rightBox.get_children().length - 1); } - } - - // Move the statusMenu to just before the dateMenu in the rightBox - let statusMenuIndex = children.indexOf(statusMenu.container); - if (statusMenuIndex != -1 && !clockBeforeStatusMenu) { - centerBox.remove_child(statusMenu.container); - rightBox.insert_child_at_index(statusMenu.container, rightBox.get_children().length - 1); - } - } - - disable() { - let centerBox = Main.panel._centerBox; - let rightBox = Main.panel._rightBox; - - // Move the dateMenu back to the centerBox - if (rightBox.get_children().indexOf(this._dateMenu.container) != -1) { - rightBox.remove_child(this._dateMenu.container); - centerBox.add_child(this._dateMenu.container); - } - - // Move the statusMenu back to the rightBox - if (rightBox.get_children().indexOf(this._statusMenu.container) != -1) { - rightBox.remove_child(this._statusMenu.container); - rightBox.add_child(this._statusMenu.container); - } - - //cleanup - this._settings = null; - } -} - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/metadata.json deleted file mode 100755 index 37b57aa2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Move the clock to right side of the panel", - "gettext-domain": "moveclock", - "name": "moveclock", - "settings-schema": "org.gnome.shell.extensions.moveclock", - "shell-version": [ - "46" - ], - "url": "https://github.com/kuvaus/moveclock", - "uuid": "moveclock@kuvaus.org", - "version": 5 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/prefs.js deleted file mode 100755 index 24955d5b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/prefs.js +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2024 kuvaus -// License GPLv3 - -import Gio from 'gi://Gio'; -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; - -import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class moveclock_preferences extends ExtensionPreferences { - fillPreferencesWindow(window) { - - // Create a preferences page - const page = new Adw.PreferencesPage({ - title: _('General'), - icon_name: 'dialog-information-symbolic', - }); - window.add(page); - - const preferences_group = new Adw.PreferencesGroup({ - title: _('Options'), - description: _('Remember to re-enable extension for changes to take effect.'), - }); - page.add(preferences_group); - - // Create a toggle to move clock before/after statusmenu - const toggleRow = new Adw.SwitchRow({ - title: _('Clock before System Menu'), - subtitle: _('Toggle whether clock is moved before (ON) or after (OFF) System Menu.'), - }); - preferences_group.add(toggleRow); - - // Bind the toggle to the extension's enabled state - const settings = this.getSettings(); - settings.bind('clock-before-statusmenu', toggleRow, 'active', Gio.SettingsBindFlags.DEFAULT); - - // Create a group for links - const links_group = new Adw.PreferencesGroup({ - title: _('Visit extension homepage:'), - }); - page.add(links_group); - - const linkButton = new Gtk.LinkButton({ - label: _('https://github.com/kuvaus/moveclock/'), - uri: 'https://github.com/kuvaus/moveclock/', - halign: Gtk.Align.START, - valign: Gtk.Align.CENTER, - hexpand: true, - }); - links_group.add(linkButton); - - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/schemas/gschemas.compiled deleted file mode 100755 index 68e8ebe0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/schemas/org.gnome.shell.extensions.moveclock.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/schemas/org.gnome.shell.extensions.moveclock.gschema.xml deleted file mode 100755 index 97bbbdd4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/moveclock@kuvaus.org/schemas/org.gnome.shell.extensions.moveclock.gschema.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - false - Move the clock before the status menu - - Toggle whether to move the clock before or after the status menu. - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/debug.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/debug.js deleted file mode 100755 index 348bec29..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/debug.js +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -/** - * Print a message in debug builds. - * - * @param {string} msg Message to print. - */ -export function message(msg) { - if (NTS.metadata['build-type'] === 'debug') - console.log(`[${NTS.metadata.name}] ${msg}`); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/enums/ColorScheme.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/enums/ColorScheme.js deleted file mode 100755 index 8459d058..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/enums/ColorScheme.js +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -/** - * Color Schemes. - * - * @readonly - * @enum {string} - */ -export const ColorScheme = { - DEFAULT: 'default', - PREFER_DARK: 'prefer-dark', - PREFER_LIGHT: 'prefer-night', -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/enums/Time.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/enums/Time.js deleted file mode 100755 index dd93ab8c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/enums/Time.js +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -/** - * Times. - * - * @readonly - * @enum {string} - */ -export const Time = { - UNKNOWN: 'unknown', - DAY: 'day', - NIGHT: 'night', -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/extension.js deleted file mode 100755 index ec5fd8b2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/extension.js +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as debug from './debug.js'; - -import { ColorSchemeSwitcher } from './modules/ColorSchemeSwitcher.js'; -import { CommandsSwitcher } from './modules/CommandsSwitcher.js'; -import { Timer } from './modules/Timer.js'; - - -export default class NightThemeSwitcher extends Extension { - #modules = []; - - enable() { - globalThis.NTS = this; - - debug.message('Enabling extension...'); - - const timer = new Timer(); - - [ - timer, - new ColorSchemeSwitcher({ timer }), - new CommandsSwitcher({ timer }), - ].forEach(module => this.#modules.push(module)); - - this.#modules.forEach(module => module.enable()); - - debug.message('Extension enabled.'); - } - - disable() { - // Extension won't be disabled in `unlock-dialog` session mode. This is - // to enable the color scheme switch while the lock screen is displayed, - // as the background image and the shell theme are visible in this mode. - debug.message('Disabling extension...'); - - this.#modules.forEach(module => module.disable()); - this.#modules = []; - - debug.message('Extension disabled.'); - - delete globalThis.NTS; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/icons/nightthemeswitcher-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/icons/nightthemeswitcher-symbolic.svg deleted file mode 100755 index 98b8a4a6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/icons/nightthemeswitcher-symbolic.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ar/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ar/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index abf0f3f8..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ar/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/bg/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/bg/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 81ceb3ac..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/bg/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/cs/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/cs/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index c0a7a813..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/cs/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/de_DE/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/de_DE/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index b7716114..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/de_DE/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/el/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/el/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index b0f907d0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/el/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/es/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/es/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 5f2dc93c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/es/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/et/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/et/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 3a6345d0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/et/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/eu/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/eu/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 818cef63..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/eu/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/fr/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/fr/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 66530b66..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/fr/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/gl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/gl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 50e63929..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/gl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/hi/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/hi/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 6002b989..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/hi/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/hu/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/hu/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 115c3b71..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/hu/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/it/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/it/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 6fab011b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/it/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ja/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ja/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 2adf7646..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ja/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nan/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nan/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index dfe051c5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nan/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nb_NO/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nb_NO/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 98cb0d61..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nb_NO/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 3b199373..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/nl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/oc/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/oc/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 8eff6993..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/oc/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/pl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/pl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 3362bb57..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/pl/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/pt_BR/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/pt_BR/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index e68b8c61..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/pt_BR/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ro/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ro/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 0049df06..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ro/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ru/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ru/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index eb376c03..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/ru/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/sv/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/sv/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 1c70fbb7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/sv/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/tr/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/tr/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index a6b02c90..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/tr/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/uk/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/uk/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 62606b95..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/uk/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/zh_CN/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/zh_CN/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index 416ea321..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/zh_CN/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/zh_TW/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/zh_TW/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo deleted file mode 100755 index b401439c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/locale/zh_TW/LC_MESSAGES/nightthemeswitcher@romainvigier.fr.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/metadata.json deleted file mode 100755 index 28e6ded6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "build-type": "release", - "description": "Automatically toggle your desktop\u2019s color scheme between light and dark, switch backgrounds and run custom commands at sunset and sunrise.", - "gettext-domain": "nightthemeswitcher@romainvigier.fr", - "name": "Night Theme Switcher", - "session-modes": [ - "unlock-dialog", - "user" - ], - "settings-schema": "org.gnome.shell.extensions.nightthemeswitcher", - "shell-version": [ - "46" - ], - "url": "https://nightthemeswitcher.romainvigier.fr", - "uuid": "nightthemeswitcher@romainvigier.fr", - "version": 77 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/ColorSchemeSwitcher.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/ColorSchemeSwitcher.js deleted file mode 100755 index 0792b4d8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/ColorSchemeSwitcher.js +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Gio from 'gi://Gio'; - -import * as debug from '../debug.js'; - -import { Time } from '../enums/Time.js'; - -import { Switcher } from './Switcher.js'; - -/** - * The Color Scheme Switcher changes the system color scheme according to the time. - */ -export class ColorSchemeSwitcher extends Switcher { - #settings; - #interfaceSettings; - #timer; - - #settingsConnections = []; - - /** - * @param {object} params Params object. - * @param {Timer} params.timer Timer to listen to. - */ - constructor({ timer }) { - const settings = NTS.getSettings(`${NTS.metadata['settings-schema']}.color-scheme`); - super({ - name: 'Color Scheme', - timer, - settings, - callback: time => this.#onTimeChanged(time), - }); - this.#timer = timer; - this.#settings = settings; - this.#interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); - } - - enable() { - super.enable(); - this.#connectSettings(); - } - - disable() { - super.disable(); - this.#disconnectSettings(); - } - - #connectSettings() { - debug.message('Connecting Color Scheme Switcher to settings...'); - this.#settingsConnections.push({ - settings: this.#settings, - id: this.#settings.connect('changed::day', this.#onColorSchemeChanged.bind(this)), - }); - this.#settingsConnections.push({ - settings: this.#settings, - id: this.#settings.connect('changed::night', this.#onColorSchemeChanged.bind(this)), - }); - this.#settingsConnections.push({ - settings: this.#interfaceSettings, - id: this.#interfaceSettings.connect('changed::color-scheme', this.#onSystemColorSchemeChanged.bind(this)), - }); - } - - #disconnectSettings() { - this.#settingsConnections.forEach(({ settings, id }) => settings.disconnect(id)); - this.#settingsConnections = []; - debug.message('Disconnected Color Scheme Switcher from settings.'); - } - - #onTimeChanged(time) { - const colorScheme = time === Time.NIGHT ? this.#settings.get_string('night') : this.#settings.get_string('day'); - this.#interfaceSettings.set_string('color-scheme', colorScheme); - } - - #onColorSchemeChanged(_settings, time) { - const colorScheme = this.#settings.get_string(time); - debug.message(`${time} color scheme changed to ${colorScheme}.`); - if (time === this.#timer.time) - this.#interfaceSettings.set_string('color-scheme', colorScheme); - } - - #onSystemColorSchemeChanged() { - const colorScheme = this.#interfaceSettings.get_string('color-scheme'); - debug.message(`System color scheme changed to ${colorScheme}.`); - this.#timer.syncTimeToColorScheme(colorScheme); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/CommandsSwitcher.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/CommandsSwitcher.js deleted file mode 100755 index bcd2737f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/CommandsSwitcher.js +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import GLib from 'gi://GLib'; - -import * as debug from '../debug.js'; - -import { Time } from '../enums/Time.js'; - -import { Switcher } from './Switcher.js'; - - -/** - * The Commands Switcher spawns commands according to the time. - */ -export class CommandsSwitcher extends Switcher { - #settings; - - /** - * @param {object} params Params object. - * @param {Timer} params.timer Timer to listen to. - */ - constructor({ timer }) { - const settings = NTS.getSettings(`${NTS.metadata['settings-schema']}.commands`); - super({ - name: 'Command', - timer, - settings, - callback: time => this.#onTimeChanged(time), - disableable: true, - }); - this.#settings = settings; - } - - #onTimeChanged(time) { - if (time === Time.UNKNOWN) - return; - const command = this.#settings.get_string(time === Time.DAY ? 'sunrise' : 'sunset'); - if (!command) - return; - GLib.spawn_async(null, ['sh', '-c', command], null, GLib.SpawnFlags.SEARCH_PATH, null); - debug.message(`Spawned ${time} command.`); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/Switcher.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/Switcher.js deleted file mode 100755 index 7f4cef62..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/Switcher.js +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import * as debug from '../debug.js'; - - -/** - * Function called when the time changes. - * - * @callback TimeChangedCallback - * @param {Time} time New time. - */ - - -/** - * The Switcher runs a callback function when the time changes. - * - */ -export class Switcher { - #name; - #timer; - #settings; - #callback; - #disableable; - - #statusConnection = null; - #timerConnection = null; - - /** - * @param {object} params Params object. - * @param {string} params.name Name of the switcher. - * @param {Timer} params.timer Timer to listen to. - * @param {Gio.Settings} params.settings Settings. - * @param {TimeChangedCallback} params.callback Callback function. - * @param {boolean} params.disableable If the switcher can be disabled using an `enabled` key in the settings. - */ - constructor({ name, timer, settings, callback, disableable = false }) { - this.#name = name; - this.#timer = timer; - this.#settings = settings; - this.#callback = callback; - this.#disableable = disableable; - } - - enable() { - debug.message(`Enabling ${this.#name} switcher...`); - if (this.#disableable) - this.#watchStatus(); - if (!this.#disableable || this.#settings.get_boolean('enabled')) { - this.#connectTimer(); - this.#onTimeChanged(); - } - debug.message(`${this.#name} switcher enabled.`); - } - - disable() { - debug.message(`Disabling ${this.#name} switcher...`); - this.#disconnectTimer(); - if (this.#disableable) - this.#unwatchStatus(); - debug.message(`${this.#name} switcher disabled.`); - } - - - #watchStatus() { - debug.message(`Watching ${this.#name} switching status...`); - this.#statusConnection = this.#settings.connect('changed::enabled', this.#onStatusChanged.bind(this)); - } - - #unwatchStatus() { - if (this.#statusConnection) { - this.#settings.disconnect(this.#statusConnection); - this.#statusConnection = null; - } - debug.message(`Stopped watching ${this.#name} switching status.`); - } - - #connectTimer() { - debug.message(`Connecting ${this.#name} switcher to Timer...`); - this.#timerConnection = this.#timer.connect('notify::time', this.#onTimeChanged.bind(this)); - } - - #disconnectTimer() { - if (this.#timerConnection) { - this.#timer.disconnect(this.#timerConnection); - this.#timerConnection = null; - } - debug.message(`Disconnected ${this.#name} switcher from Timer.`); - } - - - #onStatusChanged() { - debug.message(`${this.#name} switching has been ${this.#settings.get_boolean('enabled') ? 'enabled' : 'disabled'}.`); - this.disable(); - this.enable(); - } - - #onTimeChanged() { - this.#callback(this.#timer.time); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/Timer.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/Timer.js deleted file mode 100755 index 030b382c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/modules/Timer.js +++ /dev/null @@ -1,377 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Geoclue from 'gi://Geoclue'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; - -import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; -import { layoutManager, messageTray, wm } from 'resource:///org/gnome/shell/ui/main.js'; -import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; - -import * as debug from '../debug.js'; - -import { ColorScheme } from '../enums/ColorScheme.js'; // eslint-disable-line no-unused-vars -import { Time } from '../enums/Time.js'; - - -/** - * The Timer is responsible for signaling any time change to the other modules. - * - * They can connect to its 'time' property and query it for the current time. - * - * It will try to use the current location as a time source but will fall back - * to a manual schedule if the location services are disabled or if the user - * forced the manual schedule in the preferences. - */ -export class Timer extends GObject.Object { - #settings; - #colorSchemeSettings; - #interfaceSettings; - #locationSettings; - #time; - - #cancellable = null; - #previousKeybinding = null; - #timeTimeoutId = null; - #geoclue = null; - #geoclueLocationConnectionId = null; - #suntimesTimeoutId = null; - #manuallySetTime = false; - - #settingsConnections = []; - - static { - GObject.registerClass({ - Properties: { - time: GObject.ParamSpec.string('time', 'Time', 'Time', GObject.ParamFlags.READWRITE, Time.UNKNOWN), - }, - }, this); - } - - constructor() { - super(); - this.#settings = NTS.getSettings(`${NTS.metadata['settings-schema']}.time`); - this.#colorSchemeSettings = NTS.getSettings(`${NTS.metadata['settings-schema']}.color-scheme`); - this.#interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); - this.#locationSettings = new Gio.Settings({ schema: 'org.gnome.system.location' }); - } - - enable() { - debug.message('Enabling Timer...'); - this.#cancellable = new Gio.Cancellable(); - this.#connectSettings(); - this.#trackTime(); - if (this.#settings.get_boolean('manual-schedule')) { - debug.message('Using the manual schedule.'); - } else { - debug.message('Using location.'); - this.#trackLocation(); - this.#trackSuntimes(); - } - this.#addKeybinding(); - this.#changeTime(this.#computeTime()); - debug.message('Timer enabled.'); - } - - disable() { - debug.message('Disabling Timer...'); - this.#removeKeybinding(); - this.#untrackSuntimes(); - this.#untrackLocation(); - this.#untrackTime(); - this.#disconnectSettings(); - this.#cancellable.cancel(); - debug.message('Timer disabled.'); - } - - /** - * @param {ColorScheme} colorScheme Color scheme to sync the time to. - */ - syncTimeToColorScheme(colorScheme) { - this.#changeTime(this.#colorSchemeToTime(colorScheme), true); - } - - - get time() { - return this.#time || Time.UNKNOWN; - } - - #changeTime(time, manual = false) { - if (time === this.#time) { - if (!manual && this.#manuallySetTime) - this.#manuallySetTime = false; - return; - } - - if (!manual && time !== this.#time && this.#manuallySetTime) - return; - - this.#time = time; - this.#manuallySetTime = manual; - - debug.message(manual ? `Time manually set to ${time}.` : `Time changed to ${time}.`); - - const isMonitorFullscreen = layoutManager.monitors.some(monitor => monitor.inFullscreen); - if (this.#settings.get_boolean('fullscreen-transition') || !isMonitorFullscreen) - layoutManager.screenTransition.run(); - - this.notify('time'); - } - - - #connectSettings() { - debug.message('Connecting Timer to settings...'); - this.#settingsConnections.push({ - settings: this.#locationSettings, - id: this.#locationSettings.connect('changed::enabled', this.#onLocationStateChanged.bind(this)), - }); - this.#settingsConnections.push({ - settings: this.#settings, - id: this.#settings.connect('changed::manual-schedule', this.#onManualScheduleStateChanged.bind(this)), - }); - this.#settingsConnections.push({ - settings: this.#settings, - id: this.#settings.connect('changed::nightthemeswitcher-ondemand-keybinding', this.#onOndemandKeybindingChanged.bind(this)), - }); - // Only listen to the offset setting when not using a manual schedule - if (!this.#settings.get_boolean('manual-schedule')) { - this.#settingsConnections.push({ - settings: this.#settings, - id: this.#settings.connect('changed::offset', this.#onOffsetChanged.bind(this)), - }); - } - } - - #disconnectSettings() { - this.#settingsConnections.forEach(({ settings, id }) => settings.disconnect(id)); - this.#settingsConnections = []; - debug.message('Disconnected Timer from settings.'); - } - - - #trackTime() { - debug.message('Watching for time change...'); - this.#timeTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 1, () => { - this.#changeTime(this.#computeTime()); - return GLib.SOURCE_CONTINUE; - }); - } - - #untrackTime() { - if (this.#timeTimeoutId) { - GLib.Source.remove(this.#timeTimeoutId); - this.#timeTimeoutId = null; - } - debug.message('Stopped watching for time change.'); - } - - - #trackLocation() { - debug.message('Connecting to GeoClue...'); - Geoclue.Simple.new( - 'org.gnome.Shell', - Geoclue.AccuracyLevel.CITY, - this.#cancellable, - this.#onGeoclueReady.bind(this) - ); - } - - #untrackLocation() { - debug.message('Disconnecting from GeoClue...'); - if (this.#geoclue && this.#geoclueLocationConnectionId) { - this.#geoclue.disconnect(this.#geoclueLocationConnectionId); - this.#geoclueLocationConnectionId = null; - this.#geoclue = null; - } - debug.message('Disconnected from GeoClue.'); - } - - - #trackSuntimes() { - debug.message('Regularly updating sun times...'); - this.#suntimesTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 3600, () => { - this.#updateSuntimes(); - return GLib.SOURCE_CONTINUE; - }); - } - - #untrackSuntimes() { - if (this.#suntimesTimeoutId) { - GLib.Source.remove(this.#suntimesTimeoutId); - this.#suntimesTimeoutId = null; - } - debug.message('Stopped regularly updating sun times.'); - } - - - #addKeybinding() { - this.#previousKeybinding = this.#settings.get_strv('nightthemeswitcher-ondemand-keybinding')[0]; - if (!this.#settings.get_strv('nightthemeswitcher-ondemand-keybinding')[0]) - return; - debug.message('Adding keybinding...'); - wm.addKeybinding( - 'nightthemeswitcher-ondemand-keybinding', - this.#settings, - Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, - Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, - () => { - const time = this.time === Time.NIGHT ? Time.DAY : Time.NIGHT; - this.#changeTime(time, true); - } - ); - debug.message('Added keybinding.'); - } - - #removeKeybinding() { - if (this.#previousKeybinding) { - debug.message('Removing keybinding...'); - wm.removeKeybinding('nightthemeswitcher-ondemand-keybinding'); - debug.message('Removed keybinding.'); - } - } - - - #colorSchemeToTime(colorScheme) { - return colorScheme === this.#colorSchemeSettings.get_string('night') ? Time.NIGHT : Time.DAY; - } - - - #onLocationStateChanged() { - this.disable(); - this.enable(); - } - - #onManualScheduleStateChanged() { - this.disable(); - this.enable(); - } - - #onOffsetChanged() { - this.#updateSuntimes(); - } - - #onOndemandKeybindingChanged() { - this.#removeKeybinding(); - this.#addKeybinding(); - } - - #onGeoclueReady(_geoclue, result) { - try { - this.#geoclue = Geoclue.Simple.new_finish(result); - this.#geoclueLocationConnectionId = this.#geoclue.connect('notify::location', this.#onLocationChanged.bind(this)); - debug.message('Connected to GeoClue.'); - this.#onLocationChanged(); - } catch (e) { - const [latitude, longitude] = this.#settings.get_value('location').deepUnpack(); - if (latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180) { - console.error(`[${NTS.metadata.name}] Unable to retrieve the location, using the last known location instead.\n${e}`); - this.#updateSuntimes(); - } else { - console.error(`[${NTS.metadata.name}] Unable to retrieve the location, using the manual schedule times instead.\n${e}`); - - const source = new MessageTray.Source({ - title: NTS.metadata.name, - icon: Gio.icon_new_for_string(GLib.build_filenamev([NTS.metadata.path, 'icons', 'nightthemeswitcher-symbolic.svg'])), - }); - messageTray.add(source); - - const notification = new MessageTray.Notification( - { - source, - title: _('Unknown Location'), - body: _('A manual schedule will be used to switch the dark mode.'), - 'icon-name': 'location-services-disabled-symbolic', - } - ); - notification.addAction(_('Edit Manual Schedule'), () => NTS.openPreferences()); - - notification.connect('activated', () => NTS.openPreferences()); - - source.addNotification(notification); - - this.#settings.set_boolean('manual-schedule', true); - } - } - } - - #onLocationChanged(_geoclue, _location) { - debug.message('Location has changed.'); - const { latitude, longitude } = this.#geoclue.get_location(); - this.#settings.set_value('location', new GLib.Variant('(dd)', [latitude, longitude])); - debug.message(`Current location: (${latitude};${longitude})`); - this.#updateSuntimes(); - } - - - #computeTime() { - const sunrise = this.#settings.get_double('sunrise'); - const sunset = this.#settings.get_double('sunset'); - const datetime = GLib.DateTime.new_now_local(); - const hour = datetime.get_hour() + datetime.get_minute() / 60 + datetime.get_second() / 3600; - - // Regular schedule - if (sunrise < sunset) - return hour >= sunrise && hour < sunset ? Time.DAY : Time.NIGHT; - // Sunset happens on the day after - else if (sunrise > sunset) - return hour >= sunrise || hour < sunset ? Time.DAY : Time.NIGHT; - // Sunset and Sunrise times are identical; preserve current theme - else - return this.#time || this.#colorSchemeToTime(this.#interfaceSettings.get_string('color-scheme')); - } - - #updateSuntimes() { - const [latitude, longitude] = this.#settings.get_value('location').deepUnpack(); - - if (latitude < -90 && latitude > 90 && longitude < -180 && longitude > 180) - return; - - debug.message('Updating sun times...'); - - const rad = degrees => degrees * Math.PI / 180; - const deg = radians => radians * 180 / Math.PI; - - // Calculations from https://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html - const dtNow = GLib.DateTime.new_now_local(); - const dtZero = GLib.DateTime.new_utc(1900, 1, 1, 0, 0, 0); - - const timeSpan = dtNow.difference(dtZero); - - const date = timeSpan / 1000 / 1000 / 60 / 60 / 24 + 2; - const tzOffset = dtNow.get_utc_offset() / 1000 / 1000 / 60 / 60; - - const julianDay = date + 2415018.5 - tzOffset / 24; - const julianCentury = (julianDay - 2451545) / 36525; - const geomMeanLongSun = (280.46646 + julianCentury * (36000.76983 + julianCentury * 0.0003032)) % 360; - const geomMeanAnomSun = 357.52911 + julianCentury * (35999.05029 - 0.0001537 * julianCentury); - const eccentEarthOrbit = 0.016708634 - julianCentury * (0.000042037 + 0.0000001267 * julianCentury); - const sunEqOfCtr = Math.sin(rad(geomMeanAnomSun)) * (1.914602 - julianCentury * (0.004817 + 0.000014 * julianCentury)) + Math.sin(rad(2 * geomMeanAnomSun)) * (0.019993 - 0.000101 * julianCentury) + Math.sin(rad(3 * geomMeanAnomSun)) * 0.000289; - const sunTrueLong = geomMeanLongSun + sunEqOfCtr; - const sunAppLong = sunTrueLong - 0.00569 - 0.00478 * Math.sin(rad(125.04 - 1934.136 * julianCentury)); - const meanObliqEcliptic = 23 + (26 + ((21.448 - julianCentury * (46.815 + julianCentury * (0.00059 - julianCentury * 0.001813)))) / 60) / 60; - const obliqCorr = meanObliqEcliptic + 0.00256 * Math.cos(rad(125.04 - 1934.136 * julianCentury)); - const sunDeclin = deg(Math.asin(Math.sin(rad(obliqCorr)) * Math.sin(rad(sunAppLong)))); - const varY = Math.tan(rad(obliqCorr / 2)) * Math.tan(rad(obliqCorr / 2)); - const eqOfTime = 4 * deg(varY * Math.sin(2 * rad(geomMeanLongSun)) - 2 * eccentEarthOrbit * Math.sin(rad(geomMeanAnomSun)) + 4 * eccentEarthOrbit * varY * Math.sin(rad(geomMeanAnomSun)) * Math.cos(2 * rad(geomMeanLongSun)) - 0.5 * varY * varY * Math.sin(4 * rad(geomMeanLongSun)) - 1.25 * eccentEarthOrbit * eccentEarthOrbit * Math.sin(2 * rad(geomMeanAnomSun))); - const haSunrise = deg(Math.acos(Math.cos(rad(90.833)) / (Math.cos(rad(latitude)) * Math.cos(rad(sunDeclin))) - Math.tan(rad(latitude)) * Math.tan(rad(sunDeclin)))); - const solarNoon = (720 - 4 * longitude - eqOfTime + tzOffset * 60) / 1440; - - const timeSunrise = solarNoon - haSunrise * 4 / 1440; - const timeSunset = solarNoon + haSunrise * 4 / 1440; - - const modulo = (n, m) => ((n % m) + m) % m; - - const offset = this.#settings.get_double('offset'); - const sunrise = modulo(timeSunrise * 24 + offset, 24); - const sunset = modulo(timeSunset * 24 - offset, 24); - - this.#settings.set_double('sunrise', sunrise); - this.#settings.set_double('sunset', sunset); - - debug.message(`New sun times: (sunrise: ${sunrise}; sunset: ${sunset})`); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/BackgroundButton.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/BackgroundButton.js deleted file mode 100755 index 456628e9..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/BackgroundButton.js +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Adw from 'gi://Adw'; -import Gdk from 'gi://Gdk'; -import GdkPixbuf from 'gi://GdkPixbuf'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - - -export class BackgroundButton extends Gtk.Button { - #uri; - - static { - GObject.registerClass({ - GTypeName: 'BackgroundButton', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/BackgroundButton.ui', - InternalChildren: ['filechooser', 'thumbnail'], - Properties: { - uri: GObject.ParamSpec.string( - 'uri', - 'URI', - 'URI to the background file', - GObject.ParamFlags.READWRITE, - null - ), - thumbWidth: GObject.ParamSpec.int( - 'thumb-width', - 'Thumbnail width', - 'Width of the displayed thumbnail', - GObject.ParamFlags.READWRITE, - 0, 600, - 180 - ), - thumbHeight: GObject.ParamSpec.int( - 'thumb-height', - 'Thumbnail height', - 'Height of the displayed thumbnail', - GObject.ParamFlags.READWRITE, - 0, 600, - 180 - ), - }, - }, this); - } - - constructor({ ...params } = {}) { - super(params); - this.#setupSize(); - this.#setupDropTarget(); - this.#setupFileChooserFilter(); - } - - get uri() { - return this.#uri || null; - } - - set uri(uri) { - if (uri === this.#uri) - return; - this.#uri = uri; - this.notify('uri'); - GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - this.#updateThumbnail(); - return GLib.SOURCE_REMOVE; - }); - } - - #setupSize() { - const display = Gdk.Display.get_default(); - const monitor = display.get_monitors().get_item(0); - if (monitor.width_mm === 0 || monitor.height_mm === 0) - return; - if (monitor.width_mm > monitor.height_mm) - this.thumbHeight *= monitor.height_mm / monitor.width_mm; - else - this.thumbWidth *= monitor.width_mm / monitor.height_mm; - } - - #setupDropTarget() { - const dropTarget = Gtk.DropTarget.new(Gio.File.$gtype, Gdk.DragAction.COPY); - dropTarget.connect('drop', (_target, file, _x, _y) => { - const contentType = Gio.content_type_guess(file.get_basename(), null)[0]; - if (this.#isContentTypeSupported(contentType)) { - this.uri = file.get_uri(); - return true; - } else { - if (this.root instanceof Adw.PreferencesWindow) { - this.root.add_toast(new Adw.Toast({ - title: _('This image format is not supported.'), - timeout: 10, - })); - } - return false; - } - }); - this.add_controller(dropTarget); - } - - #setupFileChooserFilter() { - this._filechooser.filter = new Gtk.FileFilter(); - this._filechooser.filter.add_pixbuf_formats(); - this._filechooser.filter.add_mime_type('application/xml'); - } - - #getSupportedContentTypes() { - return GdkPixbuf.Pixbuf.get_formats().flatMap(format => format.get_mime_types()).concat('application/xml'); - } - - #isContentTypeSupported(contentType) { - for (const supportedContentType of this.#getSupportedContentTypes()) { - if (Gio.content_type_equals(contentType, supportedContentType)) - return true; - } - return false; - } - - vfunc_mnemonic_activate() { - this.openFileChooser(); - } - - openFileChooser() { - this._filechooser.transient_for = this.get_root(); - this._filechooser.show(); - } - - onFileChooserResponse(fileChooser, responseId) { - if (responseId !== Gtk.ResponseType.ACCEPT) - return; - this.uri = fileChooser.get_file().get_uri(); - } - - onClicked(_button) { - this.openFileChooser(); - } - - #updateThumbnail() { - this._thumbnail.paintable = null; - - if (!this.uri) - return; - - const file = Gio.File.new_for_uri(this.uri); - const contentType = Gio.content_type_guess(file.get_basename(), null)[0]; - - if (!this.#isContentTypeSupported(contentType)) - return; - - let path; - if (Gio.content_type_equals(contentType, 'application/xml')) { - const decoder = new TextDecoder('utf-8'); - const contents = decoder.decode(file.load_contents(null)[1]); - try { - path = contents.match(/(.+)<\/file>/m)[1]; - if (!this.#isContentTypeSupported(Gio.content_type_guess(path, null)[0])) - throw new Error(); - } catch (e) { - console.error(`No suitable background file found in ${file.get_path()}.\n${e}`); - return; - } - } else { - path = file.get_path(); - } - - const pixbuf = GdkPixbuf.Pixbuf.new_from_file(path); - const scale = pixbuf.width / pixbuf.height > this.thumbWidth / this.thumbHeight ? this.thumbHeight / pixbuf.height : this.thumbWidth / pixbuf.width; - const thumbPixbuf = GdkPixbuf.Pixbuf.new(pixbuf.colorspace, pixbuf.has_alpha, pixbuf.bits_per_sample, this.thumbWidth, this.thumbHeight); - pixbuf.scale( - thumbPixbuf, - 0, 0, - this.thumbWidth, this.thumbHeight, - -(pixbuf.width * scale - this.thumbWidth) / 2, -(pixbuf.height * scale - this.thumbHeight) / 2, - scale, scale, - GdkPixbuf.InterpType.TILES - ); - - this._thumbnail.paintable = Gdk.Texture.new_for_pixbuf(thumbPixbuf); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/BackgroundsPage.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/BackgroundsPage.js deleted file mode 100755 index f24695e8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/BackgroundsPage.js +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Adw from 'gi://Adw'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; - - -export class BackgroundsPage extends Adw.PreferencesPage { - static { - GObject.registerClass({ - GTypeName: 'BackgroundsPage', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/BackgroundsPage.ui', - InternalChildren: [ - 'day_button', - 'night_button', - ], - }, this); - } - - constructor({ ...params } = {}) { - super(params); - const settings = new Gio.Settings({ schema: 'org.gnome.desktop.background' }); - - settings.bind('picture-uri', this._day_button, 'uri', Gio.SettingsBindFlags.DEFAULT); - settings.bind('picture-uri-dark', this._night_button, 'uri', Gio.SettingsBindFlags.DEFAULT); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/CommandsPage.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/CommandsPage.js deleted file mode 100755 index f2b2a49f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/CommandsPage.js +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Adw from 'gi://Adw'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; - - -export class CommandsPage extends Adw.PreferencesPage { - static { - GObject.registerClass({ - GTypeName: 'CommandsPage', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/CommandsPage.ui', - InternalChildren: [ - 'enabled_switch', - 'sunrise_entry', - 'sunset_entry', - ], - }, this); - } - - constructor({ settings, ...params } = {}) { - super(params); - - settings.bind('enabled', this._enabled_switch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('sunrise', this._sunrise_entry, 'text', Gio.SettingsBindFlags.DEFAULT); - settings.bind('sunset', this._sunset_entry, 'text', Gio.SettingsBindFlags.DEFAULT); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/ContributePage.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/ContributePage.js deleted file mode 100755 index cc81a50f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/ContributePage.js +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Adw from 'gi://Adw'; -import GObject from 'gi://GObject'; - - -export class ContributePage extends Adw.PreferencesPage { - static { - GObject.registerClass({ - GTypeName: 'ContributePage', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/ContributePage.ui', - }, this); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/SchedulePage.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/SchedulePage.js deleted file mode 100755 index 8b3cd7c3..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/SchedulePage.js +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Adw from 'gi://Adw'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; - - -export class SchedulePage extends Adw.PreferencesPage { - static { - GObject.registerClass({ - GTypeName: 'SchedulePage', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/SchedulePage.ui', - InternalChildren: [ - 'manual_schedule_switch', - 'keyboard_shortcut_button', - 'schedule_sunrise_time_chooser', - 'schedule_sunset_time_chooser', - 'fullscreen_transition_switch', - ], - }, this); - } - - constructor({ settings, ...params } = {}) { - super(params); - - settings.bind('manual-schedule', this._manual_schedule_switch, 'active', Gio.SettingsBindFlags.DEFAULT); - - settings.bind('sunrise', this._schedule_sunrise_time_chooser, 'time', Gio.SettingsBindFlags.DEFAULT); - settings.bind('sunset', this._schedule_sunset_time_chooser, 'time', Gio.SettingsBindFlags.DEFAULT); - - settings.bind('fullscreen-transition', this._fullscreen_transition_switch, 'active', Gio.SettingsBindFlags.DEFAULT); - - settings.connect('changed::nightthemeswitcher-ondemand-keybinding', () => { - this._keyboard_shortcut_button.keybinding = settings.get_strv('nightthemeswitcher-ondemand-keybinding')[0]; - }); - this._keyboard_shortcut_button.connect('notify::keybinding', () => { - settings.set_strv('nightthemeswitcher-ondemand-keybinding', [this._keyboard_shortcut_button.keybinding]); - }); - this._keyboard_shortcut_button.keybinding = settings.get_strv('nightthemeswitcher-ondemand-keybinding')[0]; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/ShortcutButton.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/ShortcutButton.js deleted file mode 100755 index eb08bb8c..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/ShortcutButton.js +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import Gdk from 'gi://Gdk'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - - -export class ShortcutButton extends Gtk.Stack { - static { - GObject.registerClass({ - GTypeName: 'ShortcutButton', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/ShortcutButton.ui', - InternalChildren: ['choose_button', 'change_button', 'clear_button', 'dialog'], - Properties: { - keybinding: GObject.ParamSpec.string( - 'keybinding', - 'Keybinding', - 'Key sequence', - GObject.ParamFlags.READWRITE, - null - ), - }, - }, this); - } - - vfunc_mnemonic_activate() { - this.activate(); - } - - activate() { - if (this.keybinding) - return this._change_button.activate(); - else - return this._choose_button.activate(); - } - - openDialog() { - this._dialog.transient_for = this.get_root(); - this._dialog.present(); - } - - onKeybindingChanged(button) { - button.visible_child_name = button.keybinding ? 'edit' : 'choose'; - } - - onChooseButtonClicked(_button) { - this.openDialog(); - } - - onChangeButtonClicked(_button) { - this.openDialog(); - } - - onClearButtonClicked(_button) { - this.keybinding = ''; - } - - onKeyPressed(_widget, keyval, keycode, state) { - let mask = state & Gtk.accelerator_get_default_mod_mask(); - mask &= ~Gdk.ModifierType.LOCK_MASK; - - if (mask === 0 && keyval === Gdk.KEY_Escape) { - this._dialog.close(); - return Gdk.EVENT_STOP; - } - - if ( - !isBindingValid({ mask, keycode, keyval }) || - !isAccelValid({ mask, keyval }) - ) - return Gdk.EVENT_STOP; - - this.keybinding = Gtk.accelerator_name_with_keycode( - null, - keyval, - keycode, - mask - ); - this._dialog.close(); - return Gdk.EVENT_STOP; - } -} - - -/** - * Check if the given keyval is forbidden. - * - * @param {number} keyval The keyval number. - * @returns {boolean} `true` if the keyval is forbidden. - */ -function isKeyvalForbidden(keyval) { - const forbiddenKeyvals = [ - Gdk.KEY_Home, - Gdk.KEY_Left, - Gdk.KEY_Up, - Gdk.KEY_Right, - Gdk.KEY_Down, - Gdk.KEY_Page_Up, - Gdk.KEY_Page_Down, - Gdk.KEY_End, - Gdk.KEY_Tab, - Gdk.KEY_KP_Enter, - Gdk.KEY_Return, - Gdk.KEY_Mode_switch, - ]; - return forbiddenKeyvals.includes(keyval); -} - -/** - * Check if the given key combo is a valid binding - * - * @param {{mask: number, keycode: number, keyval:number}} combo An object - * representing the key combo. - * @returns {boolean} `true` if the key combo is a valid binding. - */ -function isBindingValid({ mask, keycode, keyval }) { - if ((mask === 0 || mask === Gdk.SHIFT_MASK) && keycode !== 0) { - if ( - (keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) || - (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) || - (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) || - (keyval >= Gdk.KEY_kana_fullstop && keyval <= Gdk.KEY_semivoicedsound) || - (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) || - (keyval >= Gdk.KEY_Serbian_dje && keyval <= Gdk.KEY_Cyrillic_HARDSIGN) || - (keyval >= Gdk.KEY_Greek_ALPHAaccent && keyval <= Gdk.KEY_Greek_omega) || - (keyval >= Gdk.KEY_hebrew_doublelowline && keyval <= Gdk.KEY_hebrew_taf) || - (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) || - (keyval >= Gdk.KEY_Hangul_Kiyeog && keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) || - (keyval === Gdk.KEY_space && mask === 0) || - isKeyvalForbidden(keyval) - ) - return false; - } - return true; -} - -/** - * Check if the given key combo is a valid accelerator. - * - * @param {{mask: number, keyval:number}} combo An object representing the key - * combo. - * @returns {boolean} `true` if the key combo is a valid accelerator. - */ -function isAccelValid({ mask, keyval }) { - return Gtk.accelerator_valid(keyval, mask) || (keyval === Gdk.KEY_Tab && mask !== 0); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/TimeChooser.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/TimeChooser.js deleted file mode 100755 index e651b844..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/preferences/TimeChooser.js +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -import GDesktopEnums from 'gi://GDesktopEnums'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - - -export class TimeChooser extends Gtk.Widget { - #clockFormat; - #interfaceSettings; - - static { - GObject.registerClass({ - GTypeName: 'TimeChooser', - Template: 'resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/TimeChooser.ui', - InternalChildren: ['clock_format_stack', 'hours_12', 'minutes_12', 'hours_24', 'minutes_24', 'am_toggle_button', 'pm_toggle_button'], - Properties: { - time: GObject.ParamSpec.double( - 'time', - 'Time', - 'The time of the chooser', - GObject.ParamFlags.READWRITE, - 0, - 24, - 0 - ), - }, - }, this); - } - - constructor({ ...params } = {}) { - super(params); - this.#interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); - this.#interfaceSettings.connect('changed::clock-format', this.#onClockFormatChanged.bind(this)); - this.#onClockFormatChanged(); - } - - #onClockFormatChanged(_settings) { - this.#clockFormat = this.#interfaceSettings.get_enum('clock-format'); - this.#syncClockFormatStack(); - } - - #syncClockFormatStack() { - this._clock_format_stack.set_visible_child_name(this.#clockFormat === GDesktopEnums.ClockFormat['12H'] ? '12h' : '24h'); - } - - #convertTimeTo24hFormat(time) { - const hours = Math.trunc(time); - const minutes = Math.round((time - hours) * 60); - return { hours, minutes }; - } - - #convertTimeTo12hFormat(time) { - const { hours: hours24, minutes } = this.#convertTimeTo24hFormat(time); - const hours = hours24 % 12; - const isPm = hours24 > 12; - return { hours, minutes, isPm }; - } - - #convert24hFormatToTime({ hours, minutes }) { - return hours + minutes / 60; - } - - #convert12hFormatToTime({ hours, minutes, isPm }) { - return this.#convert24hFormatToTime({ - hours: hours + Number(isPm) * 12, - minutes, - }); - } - - onTimeChanged(_chooser) { - const time = this.time; - - const clock12 = this.#convertTimeTo12hFormat(time); - this._hours_12.value = clock12.hours; - this._minutes_12.value = clock12.minutes; - this._am_toggle_button.active = !clock12.isPm; - this._pm_toggle_button.active = clock12.isPm; - - const clock24 = this.#convertTimeTo24hFormat(time); - this._hours_24.value = clock24.hours; - this._minutes_24.value = clock24.minutes; - } - - onValueChanged(_widget) { - this.time = this.#clockFormat === GDesktopEnums.ClockFormat['12H'] - ? this.#convert12hFormatToTime({ hours: this._hours_12.value, minutes: this._minutes_12.value, isPm: this._pm_toggle_button.active }) - : this.#convert24hFormatToTime({ hours: this._hours_24.value, minutes: this._minutes_24.value }); - } - - onOutputChanged(spin) { - spin.text = spin.value.toString().padStart(2, '0'); - return true; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/prefs.js deleted file mode 100755 index bc1c3c41..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/prefs.js +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: Night Theme Switcher Contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -'use strict'; - -import Adw from 'gi://Adw'; -import Gdk from 'gi://Gdk'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - - -export default class NightThemeSwitcherPreferences extends ExtensionPreferences { - /** - * Fill the PreferencesWindow. - * - * @param {Adw.PreferencesWindow} window The PreferencesWindow to fill. - */ - async fillPreferencesWindow(window) { - // Load resources - const resource = Gio.Resource.load(GLib.build_filenamev([this.path, 'resources', 'preferences.gresource'])); - Gio.resources_register(resource); - - // Load icons - const iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - iconTheme.add_resource_path('/org/gnome/Shell/Extensions/nightthemeswitcher/preferences/icons'); - - // Set window properties - window.search_enabled = true; - window.set_default_size(500, 630); - - // Add a dummy page until the dynamics imports are done - const dummyPage = new Adw.PreferencesPage(); - window.add(dummyPage); - - // Dynamically import all classes - const { BackgroundButton } = await import('./preferences/BackgroundButton.js'); - const { BackgroundsPage } = await import('./preferences/BackgroundsPage.js'); - const { CommandsPage } = await import('./preferences/CommandsPage.js'); - const { ContributePage } = await import('./preferences/ContributePage.js'); - const { SchedulePage } = await import('./preferences/SchedulePage.js'); - const { ShortcutButton } = await import('./preferences/ShortcutButton.js'); - const { TimeChooser } = await import('./preferences/TimeChooser.js'); - - // Make sure all GObjects are registered - GObject.type_ensure(BackgroundButton); - GObject.type_ensure(BackgroundsPage); - GObject.type_ensure(CommandsPage); - GObject.type_ensure(ContributePage); - GObject.type_ensure(SchedulePage); - GObject.type_ensure(ShortcutButton); - GObject.type_ensure(TimeChooser); - - // Remove the dummy page - window.remove(dummyPage); - - // Add all pages - [ - new SchedulePage({ settings: this.getSettings(`${this.metadata['settings-schema']}.time`) }), - new BackgroundsPage(), - new CommandsPage({ settings: this.getSettings(`${this.metadata['settings-schema']}.commands`) }), - new ContributePage(), - ].forEach(page => window.add(page)); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/resources/preferences.gresource b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/resources/preferences.gresource deleted file mode 100755 index cc941d76..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/resources/preferences.gresource and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/schemas/gschemas.compiled deleted file mode 100755 index 2da9af6c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml deleted file mode 100755 index f73dc833..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/nightthemeswitcher@romainvigier.fr/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - 0 - - - - - false - - - "" - - - "" - - - - - t']]]> - - - true - - - false - - - - 6 - - - - 20 - - - (91,181) - - - - 0.4 - - - - - "default" - - - "prefer-dark" - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/extension.js deleted file mode 100755 index 4de3cfdf..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/extension.js +++ /dev/null @@ -1,236 +0,0 @@ -import GLib from 'gi://GLib'; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as Panel from 'resource:///org/gnome/shell/ui/panel.js'; -import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; - -const _origAddToPanelBox = Panel.Panel.prototype._addToPanelBox; - -let timeout_id = null; -let settings = null; -let order_arr_left = null; -let order_arr_center = null; -let order_arr_right = null; -let blacklist_array = null; -let order_arr = null; - -export default class OrderIcons extends Extension { - enable() { - settings = this.getSettings() - order_arr_left = settings.get_value("order-icons-left").deep_unpack() - order_arr_center = settings.get_value("order-icons-center").deep_unpack() - order_arr_right = settings.get_value("order-icons-right").deep_unpack() - blacklist_array = settings.get_value("icons-blacklist").deep_unpack() - Panel.Panel.prototype._redrawIndicators = _redrawIndicators; - Panel.Panel.prototype._addToPanelBox = _addToPanelBox; - Main.panel._redrawIndicators(); - this.settingsIDs = []; - this.settingsIDs.push(settings.connect('changed::order-icons-left', _ => { - Main.panel._redrawIndicators() - })); - this.settingsIDs.push(settings.connect('changed::order-icons-center', _ => { - Main.panel._redrawIndicators() - })); - this.settingsIDs.push(settings.connect('changed::order-icons-right', _ => { - Main.panel._redrawIndicators() - })); - this.settingsIDs.push(settings.connect('changed::icons-blacklist', _ => { - Main.panel._redrawIndicators() - })); - } - - disable() { - Panel.Panel.prototype._redrawIndicators = undefined; - Panel.Panel.prototype._addToPanelBox = _origAddToPanelBox; - this.settingsIDs.forEach(id => settings.disconnect(id)); - GLib.Source.remove(timeout_id); - timeout_id = null; - order_arr_left = null; - order_arr_center = null; - order_arr_right = null; - blacklist_array = null; - this.settingsIDs = null; - settings = null; - } -} - - - -function _redrawIndicators() { - order_arr_left = settings.get_value("order-icons-left").deep_unpack() - order_arr_center = settings.get_value("order-icons-center").deep_unpack() - order_arr_right = settings.get_value("order-icons-right").deep_unpack() - blacklist_array = settings.get_value("icons-blacklist").deep_unpack() - for (const k in this.statusArea) { - const role = k; - const indicator = this.statusArea[k]; - let box = indicator.get_parent().get_parent(); - if (box == undefined) continue - this._addToPanelBox(role, indicator, 0, box) - } - -} - - -function _addToPanelBox(role, indicator, position, box) { - - const container = indicator.container; - container.show(); - const parent = container.get_parent(); - if (parent) { - parent.remove_child(container); - } - - this.statusArea[role] = indicator; - // not ideal, but due to recent changes in appindicator-extension we have to wait for the ID to become available - let in_blacklist = false; - waitForId(indicator, role).then(() => { - let position_corr = getRelativePosition(indicator, role, box.name, this.statusArea); - let testName = getTestName(indicator, role); - if (blacklist_array.includes(testName)) { - in_blacklist = true; - } - else { - setSettingValues(testName, box); - box.insert_child_at_index(container, position_corr ? position_corr : position); - } - }).catch((error) => { console.log(error) }) - if (in_blacklist) { - delete this.statusArea[role]; - } - else { - if (indicator.menu) { - this.menuManager.addMenu(indicator.menu); - } - const destroyId = indicator.connect('destroy', (emitter) => { - delete this.statusArea[role]; - emitter.disconnect(destroyId); - }); - indicator.connect('menu-set', this._onMenuSet.bind(this)); - this._onMenuSet(indicator); - } -} - - -function setSettingValues(name, box) { - - let index = null; - let index_arr = null; - - if (box.name == "panelRight") { - index = getSettingsPosition(name, order_arr_right); - index_arr = order_arr_right.indexOf(name); - if (index_arr == -1) { - order_arr_right.splice(index, 0, name); - } - } - if (box.name == "panelCenter") { - index = getSettingsPosition(name, order_arr_center); - index_arr = order_arr_center.indexOf(name); - if (index_arr == -1) { - order_arr_center.splice(index, 0, name); - } - } - if (box.name == "panelLeft") { - index = getSettingsPosition(name, order_arr_left); - index_arr = order_arr_left.indexOf(name); - if (index_arr == -1) { - order_arr_left.splice(index, 0, name); - } - } - - settings.set_value("order-icons-right", new GLib.Variant('as', order_arr_right)) - settings.set_value("order-icons-center", new GLib.Variant('as', order_arr_center)) - settings.set_value("order-icons-left", new GLib.Variant('as', order_arr_left)) -} - - -function getRelativePosition(indicator, role, boxName, statusArea) { - const indicatorTestName = getTestName(indicator, role); - if (boxName == "panelRight") - order_arr = order_arr_right - else if (boxName == "panelCenter") - order_arr = order_arr_center - else if (boxName == "panelLeft") - order_arr = order_arr_left - const indicatorPosition = getSettingsPosition(indicatorTestName, order_arr); - - let ctr = 0 - for (const k in statusArea) { - if (k == role) continue - if (statusArea[k].get_parent().get_parent() != null && boxName === statusArea[k].get_parent().get_parent().get_name()) { - const toTest = getTestName(statusArea[k], k); - let setPosition = getSettingsPosition(toTest, order_arr); - if (setPosition == null) { - setPosition = 0; - } - if (setPosition < indicatorPosition) { - ctr = ctr + 1; - } - - } - } - return ctr -} - - -function until(conditionFunction) { - const poll = resolve => { - if (conditionFunction()) { - resolve(); - return GLib.G_SOURCE_REMOVE; - } else { - timeout_id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, _ => poll(resolve)); - return GLib.G_SOURCE_REMOVE; - } - } - return new Promise(poll); -} - - - -function getTestName(indicator, name) { - let toTest = name; - if (indicator._indicator) { - let id = indicator._indicator.id; - if (name.startsWith('appindicator-')) { - if (id.startsWith('chrome_status_icon')) { - // electron apps don't give a good ID with newer releases, so we have to revert to command line and try to get something useful - let commandLine = indicator._indicator._commandLine; - let commandLineSplit = commandLine.split('/'); - toTest = commandLineSplit[commandLineSplit.length - 1]; - } - else { - toTest = id; - } - } - } - if (toTest) { - const match = toTest.match(/appindicator-legacy:(.*?):/); - if (match && match.length > 1) { - return match[1]; - } - if (toTest.includes('dropbox')) { - // dropbox needs special treatment because it appends the pid to the id. - // So we need to hardcode the name - return 'dropbox'; - } - return toTest; - } - let ret = name.split("/") - return ret[ret.length - 1].replaceAll("_", "-") -} - -async function waitForId(indicator, name) { - if (indicator._indicator && name.startsWith('appindicator-')) { - await until(_ => (indicator._indicator.id != undefined && indicator._indicator._commandLine != undefined)); - } - return true -} - -function getSettingsPosition(name, arr) { - if (arr == null) { - return 0; - } - let index = arr.indexOf(name); - return index != -1 ? index : 0; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/metadata.json deleted file mode 100755 index 659ccadc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/metadata.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "author": "Andreas Angerer", - "description": "Orders icons from extensions in the top bar", - "extension-id": "order-extensions", - "gettext-domain": "order extensions", - "name": "Order Gnome Shell extensions", - "settings-schema": "org.gnome.shell.extensions.order-icons", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/andia89/order-icons", - "uuid": "order-extensions@wa4557.github.com", - "version": 22 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/prefs.js deleted file mode 100755 index e312cd1e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/prefs.js +++ /dev/null @@ -1,399 +0,0 @@ -// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- - -/* exported init, buildPrefsWidget */ - -import GObject from 'gi://GObject'; -import GLib from 'gi://GLib'; -import Gtk from 'gi://Gtk'; - -import { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - - -export default class OrderIconsPreferences extends ExtensionPreferences { - getPreferencesWidget() { - return new OrderIconsPreferencesBox(this); - } -} - -const OrderIconsPreferencesBox = GObject.registerClass( - class OrderIconsPreferencesBox extends Gtk.Box { - _init(extension) { - super._init({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 30 - }); - this._settings = extension.getSettings(); - - // Boxes for list stores - this.right_order_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 8, - margin_start: 30, - margin_end: 0, - margin_top: 30, - margin_bottom: 30 - }); - this.center_order_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 8, - margin_start: 30, - margin_end: 0, - margin_top: 30, - margin_bottom: 30 - }); - this.left_order_hbox = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 8, - margin_start: 30, - margin_end: 0, - margin_top: 30, - margin_bottom: 30 - }); - - // Button boxes - this.left_button_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 8, - margin_start: 30, - margin_end: 30, - margin_top: 30, - margin_bottom: 30 - }); - - this.center_button_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 8, - margin_start: 30, - margin_end: 30, - margin_top: 30, - margin_bottom: 30 - }); - - this.right_button_vbox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - spacing: 8, - margin_start: 30, - margin_end: 30, - margin_top: 30, - margin_bottom: 30 - }); - - const button_up_left = new Gtk.Button() - button_up_left.set_icon_name("go-up-symbolic"); - const button_down_left = new Gtk.Button() - button_down_left.set_icon_name("go-down-symbolic"); - const button_del_left = new Gtk.Button() - button_del_left.set_icon_name("edit-delete-symbolic"); - const button_blacklist_left = new Gtk.Button(); - button_blacklist_left.set_icon_name('action-unavailable-symbolic'); - - button_up_left.set_tooltip_text( _('Moves selected entry up')); - button_down_left.set_tooltip_text( _('Moves selected entry down')); - button_del_left.set_tooltip_text( _('Removes entry from this list')); - button_blacklist_left.set_tooltip_text( _('Removes/reenables icon from top panel (restart of extension required)')); - - this.left_button_vbox.append(button_up_left); - this.left_button_vbox.append(button_down_left); - this.left_button_vbox.append(button_del_left); - this.left_button_vbox.append(button_blacklist_left); - - - const button_up_center = new Gtk.Button() - button_up_center.set_icon_name("go-up-symbolic"); - const button_down_center = new Gtk.Button() - button_down_center.set_icon_name("go-down-symbolic"); - const button_del_center = new Gtk.Button() - button_del_center.set_icon_name("edit-delete-symbolic"); - const button_blacklist_center = new Gtk.Button(); - button_blacklist_center.set_icon_name('action-unavailable-symbolic'); - - button_up_center.set_tooltip_text( _('Moves selected entry up')); - button_down_center.set_tooltip_text( _('Moves selected entry down')); - button_del_center.set_tooltip_text( _('Removes entry from this list')); - button_blacklist_center.set_tooltip_text( _('Removes/reenables icon from top panel (restart of extension required)')); - - this.center_button_vbox.append(button_up_center); - this.center_button_vbox.append(button_down_center); - this.center_button_vbox.append(button_del_center); - this.center_button_vbox.append(button_blacklist_center); - - - const button_up_right = new Gtk.Button() - button_up_right.set_icon_name("go-up-symbolic"); - const button_down_right = new Gtk.Button() - button_down_right.set_icon_name("go-down-symbolic"); - const button_del_right = new Gtk.Button() - button_del_right.set_icon_name("edit-delete-symbolic"); - const button_blacklist_right = new Gtk.Button(); - button_blacklist_right.set_icon_name('action-unavailable-symbolic'); - - button_up_right.set_tooltip_text( _('Moves selected entry up')); - button_down_right.set_tooltip_text( _('Moves selected entry down')); - button_del_right.set_tooltip_text( _('Removes entry from this list')); - button_blacklist_right.set_tooltip_text( _('Removes/reenables icon from top panel (restart of extension required)')); - - this.right_button_vbox.append(button_up_right); - this.right_button_vbox.append(button_down_right); - this.right_button_vbox.append(button_del_right); - this.right_button_vbox.append(button_blacklist_right); - - - const cell_renderer = new Gtk.CellRendererText({ - editable: false - }); - - this.blacklist_array = this._settings.get_value('icons-blacklist').deep_unpack(); - - // right box - this.order_right_store = new Gtk.ListStore(); - this.order_right_store.set_column_types([ - GObject.TYPE_STRING, GObject.TYPE_BOOLEAN - ]); - const right_order_array = this._settings.get_value('order-icons-right').deep_unpack() - right_order_array.forEach(value => { - let is_blacklisted = this.blacklist_array.includes(value) - this.order_right_store.set(this.order_right_store.append(), [0, 1], [value, is_blacklisted]) - }); - - const right_order_tree_view = new Gtk.TreeView({ - model: this.order_right_store, - hexpand: true, - vexpand: true - }); - right_order_tree_view.set_reorderable(true); - this.order_right_store.connect("row-deleted", () => { this._orderChanged('panelRight', this.order_right_store) }); - const right_order_column = new Gtk.TreeViewColumn({ - title: "Order Indicators", - }); - const right_order_window = new Gtk.ScrolledWindow() - right_order_window.set_child(right_order_tree_view) - - // center box - this.order_center_store = new Gtk.ListStore(); - this.order_center_store.set_column_types([ - GObject.TYPE_STRING, GObject.TYPE_BOOLEAN - ]); - const center_order_array = this._settings.get_value('order-icons-center').deep_unpack() - center_order_array.forEach(value => { - let is_blacklisted = this.blacklist_array.includes(value) - this.order_center_store.set(this.order_center_store.append(), [0, 1], [value, is_blacklisted]) - }); - const center_order_tree_view = new Gtk.TreeView({ - model: this.order_center_store, - hexpand: true, - vexpand: true - }); - center_order_tree_view.set_reorderable(true); - this.order_center_store.connect("row-deleted", () => { this._orderChanged('panelCenter', this.order_center_store) }); - const center_order_column = new Gtk.TreeViewColumn({ - title: "Order Indicators", - }); - const center_order_window = new Gtk.ScrolledWindow() - center_order_window.set_child(center_order_tree_view) - - - // left box - this.order_left_store = new Gtk.ListStore(); - this.order_left_store.set_column_types([ - GObject.TYPE_STRING, GObject.TYPE_BOOLEAN - ]); - const left_order_array = this._settings.get_value('order-icons-left').deep_unpack() - left_order_array.forEach(value => { - let is_blacklisted = this.blacklist_array.includes(value) - this.order_left_store.set(this.order_left_store.append(), [0, 1], [value, is_blacklisted]) - }); - const left_order_tree_view = new Gtk.TreeView({ - model: this.order_left_store, - hexpand: true, - vexpand: true - }); - left_order_tree_view.set_reorderable(true); - this.order_left_store.connect("row-deleted", () => { this._orderChanged('panelLeft', this.order_left_store) }); - const left_order_column = new Gtk.TreeViewColumn({ - title: "Order Indicators", - }); - - const left_order_window = new Gtk.ScrolledWindow() - left_order_window.set_child(left_order_tree_view) - - left_order_column.pack_start(cell_renderer, true); - left_order_column.add_attribute(cell_renderer, 'text', 0); - left_order_column.add_attribute(cell_renderer, 'strikethrough', 1); - left_order_tree_view.insert_column(left_order_column, 0); - left_order_tree_view.set_grid_lines(Gtk.TreeViewGridLines.BOTH); - - center_order_column.pack_start(cell_renderer, true); - center_order_column.add_attribute(cell_renderer, 'text', 0); - center_order_column.add_attribute(cell_renderer, 'strikethrough', 1); - center_order_tree_view.insert_column(center_order_column, 0); - center_order_tree_view.set_grid_lines(Gtk.TreeViewGridLines.BOTH); - - right_order_column.pack_start(cell_renderer, true); - right_order_column.add_attribute(cell_renderer, 'text', 0); - right_order_column.add_attribute(cell_renderer, 'strikethrough', 1); - right_order_tree_view.insert_column(right_order_column, 0); - right_order_tree_view.set_grid_lines(Gtk.TreeViewGridLines.BOTH); - - - button_up_left.connect("clicked", _ => this._onButtonUpClicked("panelLeft", left_order_tree_view)); - button_down_left.connect("clicked", _ => this._onButtonDownClicked("panelLeft", left_order_tree_view)); - button_del_left.connect("clicked", _ => this._onButtonDelClicked("panelLeft", left_order_tree_view)); - - button_up_center.connect("clicked", _ => this._onButtonUpClicked("panelCenter", center_order_tree_view)); - button_down_center.connect("clicked", _ => this._onButtonDownClicked("panelCenter", center_order_tree_view)); - button_del_center.connect("clicked", _ => this._onButtonDelClicked("panelCenter", center_order_tree_view)); - - button_up_right.connect("clicked", _ => this._onButtonUpClicked("panelRight", right_order_tree_view)); - button_down_right.connect("clicked", _ => this._onButtonDownClicked("panelRight", right_order_tree_view)); - button_del_right.connect("clicked", _ => this._onButtonDelClicked("panelRight", right_order_tree_view)); - - button_blacklist_center.connect('clicked', _ => this._onButtonBlacklistClicked(center_order_tree_view, this.order_center_store)); - button_blacklist_left.connect('clicked', _ => this._onButtonBlacklistClicked(left_order_tree_view, this.order_left_store)); - button_blacklist_right.connect('clicked', _ => this._onButtonBlacklistClicked(right_order_tree_view, this.order_right_store)); - - this.left_order_hbox.append(left_order_window); - this.left_order_hbox.append(this.left_button_vbox); - this.center_order_hbox.append(center_order_window); - this.center_order_hbox.append(this.center_button_vbox); - this.right_order_hbox.append(right_order_window); - this.right_order_hbox.append(this.right_button_vbox); - - - - this.notebook = new Gtk.Notebook(); - this.notebook.append_page(this.right_order_hbox, - new Gtk.Label({ - label: _('Right Panel') - })); - this.notebook.append_page(this.center_order_hbox, - new Gtk.Label({ - label: _('Center Panel') - })); - this.notebook.append_page(this.left_order_hbox, - new Gtk.Label({ - label: _('Left Panel') - })); - this.append(this.notebook); - } - - - _onButtonUpClicked(panel, treeView) { - let selection = treeView.get_selection(); - let [isSelected, model, selected_row] = selection.get_selected(); - if (isSelected == false) return - - let [index2, listStore] = selection.get_selected_rows() - let index = index2[0].get_indices() - let index_above = parseInt(index) - 1 - if (index_above >= 0) { - - const returnIter = listStore.iter_nth_child(null, index_above); - const [success_above, iter_above] = returnIter; - if (!success_above) - return; - listStore.move_before(selected_row, iter_above) - this._orderChanged(panel, listStore) - } - - } - - - _onButtonDownClicked(panel, treeView) { - let selection = treeView.get_selection(); - let [isSelected, model, selected_row] = selection.get_selected(); - if (isSelected == false) return - - let [index2, listStore] = selection.get_selected_rows() - let index = index2[0].get_indices() - let index_below = parseInt(index) + 1 - let length_store = listStore.iter_n_children(null); - if (index_below < length_store) { - - const returnIter = listStore.iter_nth_child(null, index_below); - const [success_above, iter_below] = returnIter; - if (!success_above) - return; - listStore.move_after(selected_row, iter_below) - this._orderChanged(panel, listStore) - } - } - - _orderChanged(panel, listStore) { - let length_store = listStore.iter_n_children(null); - let new_order_arr = [] - for (let i = 0; i < length_store; i++) { - const returnIter = listStore.iter_nth_child(null, i); - const [success, iterList] = returnIter; - if (!success) - break; - if (iterList) { - new_order_arr.push(listStore.get_value(iterList, 0)); - } else { - break; - } - } - if (panel == "panelRight") - this._settings.set_value("order-icons-right", new GLib.Variant('as', new_order_arr)) - else if (panel == "panelCenter") - this._settings.set_value("order-icons-center", new GLib.Variant('as', new_order_arr)) - else if (panel == "panelLeft") - this._settings.set_value("order-icons-left", new GLib.Variant('as', new_order_arr)) - } - - _onButtonDelClicked(panel, treeview) { - let selection = treeview.get_selection(); - let [isSelected, model, selected_row] = selection.get_selected(); - if (isSelected == false) return - - let [index2, listStore] = selection.get_selected_rows() - let index = index2[0].get_indices() - - let length_store = listStore.iter_n_children(null); - - listStore.remove(selected_row) - let new_order_arr = [] - for (let i = 0; i < length_store; i++) { - const returnIter = listStore.iter_nth_child(null, i); - const [success, iterList] = returnIter; - if (!success) - break; - if (iterList) { - new_order_arr.push(listStore.get_value(iterList, 0)); - } else { - break; - } - } - if (panel == "panelRight") - this._settings.set_value("order-icons-right", new GLib.Variant('as', new_order_arr)) - else if (panel == "panelCenter") - this._settings.set_value("order-icons-center", new GLib.Variant('as', new_order_arr)) - else if (panel == "panelLeft") - this._settings.set_value("order-icons-left", new GLib.Variant('as', new_order_arr)) - } - - _onButtonBlacklistClicked(treeView, listStoreToSet) { - let selection = treeView.get_selection(); - let [isSelected, model, selected_row] = selection.get_selected(); - if (isSelected == false) return - - let [indexSelected, listStore] = selection.get_selected_rows() - let index = indexSelected[0].get_indices() - const selectedElement = listStore.iter_nth_child(null, index); - const [success, iterList] = selectedElement; - if (!success){ - return; - } - const selectedValue = listStore.get_value(iterList, 0); - const inBlacklistArray = this.blacklist_array.indexOf(selectedValue); - if (inBlacklistArray > -1){ - this.blacklist_array.splice(inBlacklistArray, 1); - listStoreToSet.set(iterList, [1], [false]) - } - else { - this.blacklist_array.push(selectedValue) - listStoreToSet.set(iterList, [1], [true]) - } - this._settings.set_value("icons-blacklist", new GLib.Variant('as', this.blacklist_array)) - } - - }); \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/schemas/gschemas.compiled deleted file mode 100755 index c69797a4..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/schemas/org.gnome.shell.extensions.order-icons.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/schemas/org.gnome.shell.extensions.order-icons.gschema.xml deleted file mode 100755 index 4999a8dc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/order-extensions@wa4557.github.com/schemas/org.gnome.shell.extensions.order-icons.gschema.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - [] - Order icons left box - Order icons according to this list - - - [] - Order icons center box - Order icons according to this list - - - [] - Order icons right box - Order icons according to this list - - - [] - Blacklist icons - Blacklist icons from showing up - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/COPYING b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/COPYING deleted file mode 100755 index e55e5b8a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/NEWS b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/NEWS deleted file mode 100755 index 4217e92f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/NEWS +++ /dev/null @@ -1,1439 +0,0 @@ -46.0 -==== -* system-monitor: Fix net speed [Florian; !313] -* Misc. bug fixes and cleanups [Aral; !311] - -Contributors: - Aral Balkan, Florian Müllner - -Translators: - Anders Jonsson [sv], Piotr Drąg [pl], Balázs Úr [hu], Milo Casagrande [it], - Quentin PAGÈS [oc], Athmane MOKRAOUI [kab], Changwoo Ryu [ko], - Ask Hjorth Larsen [da] - -46.rc -===== -* Fix window previews in workspace indicator [Florian; !304] -* Fix menu ornament in workspace indicator [Florian; !305] -* Misc. bug fixes and cleanups [Florian; !306, !309] - -Contributors: - Florian Müllner - -Translators: - Danial Behzadi [fa], Ekaterine Papava [ka], Sabri Ünal [tr], Artur S0 [ru], - Yuri Chornoivan [uk], Vasil Pupkin [be], Asier Sarasua Garmendia [eu], - Yaron Shahrabani [he], Brage Fuglseth [nb], Nathan Follens [nl], - Aurimas Černius [lt], Matej Urbančič [sl], Boyuan Yang [zh_CN], - Kukuh Syafaat [id], Fran Dieguez [gl], Andi Chandler [en_GB], - Baurzhan Muftakhidinov [kk], Rūdolfs Mazurs [lv], Guillaume Bernard [fr], - Daniel Mustieles [es], Jiri Grönroos [fi] - -46.beta -======= -* apps-menu: Rename Applications to Apps [Allan; !299] -* Misc. bug fixes and cleanups [Florian; !296, !297, !300, !301, !302] - -Contributors: - Allan Day, Florian Müllner - -Translators: - Gabriel Brand [de], Daniel Rusek [cs], Fran Dieguez [gl], - Aefgh Threenine [th], Vasil Pupkin [be], Artur S0 [ru], Yosef Or Boczko [he], - Sabri Ünal [tr] - -46.alpha -======== -* workspace-indicator: Fix initial preview visibility [Florian; !280, !292] -* screenshot-window-sizer: Fix cycling between sizes backwards [Florian; !284] -* Add back overview in Classic session [Florian; !287] -* Allow running Classic session headless [Jonas; !289] -* window-list: Fix buttons not being clickable at the screen edge - [Florian; !291] -* Add system-monitor extension [Florian; !277] -* Fixed crash [Florian; !290] -* Misc. bug fixes and cleanups [Florian; !276, !275, !278, !281, !286, !288] - -Contributors: - Jonas Ådahl, Florian Müllner - -Translators: - Kristjan SCHMIDT [eo], Brage Fuglseth [nb] - -45.0 -==== - -Contributors: - Andre Klapper - -Translators: - Bruce Cowan [en_GB] - -45.rc -===== -* Misc. bug fixes and cleanups [Florian; !267, !224, !272] - -Contributors: - Florian Müllner - -Translators: - Sabri Ünal [tr], Florentina Musat [ro], A S Alam [pa] - -45.beta -======= -* Port extensions to ESM [Florian; !259, !266, !268, !269] -* Misc. bug fixes and cleanups [Florian; !260, !261, !262, !263, !264] - -Contributors: - Florian Müllner - -Translators: - Efstathios Iosifidis [el] - -45.alpha -======== -* window-list: Modernize default styling [Alexander; !253] -* Replace classic styling with built-in light style [Florian; !254] -* window-list: Add tooltip for long window titles [Arik; !251] -* light-style: New extension [Florian; !256] -* Misc. bug fixes and cleanups [Florian; !255, !257] - -Contributors: - Florian Müllner, Arik W, Alexander Weichart - -44.0 -==== -* Bump version - -44.rc -===== -* Bump version - -44.beta -======= -* Tweak menu alignment [robxnano; !246] - -Contributors: - Florian Müllner, robxnano - -Translators: - Vasil Pupkin [be] - -43.1 -==== -* Fixed crash [Florian; !243] -* Misc. bug fixes and cleanups [mowemcfc; !244] - -Contributors: - Florian Müllner, mowemcfc - -Translators: - Sabri Ünal [tr] - -43.0 -==== - -Contributors: - Florian Müllner - -Translators: - Pawan Chitrakar [ne], Zurab Kargareteli [ka], Aleksandr Melman [ru] - -43.rc -===== -* Misc. bug fixes and cleanups [Florian; !240] - -Contributors: - Florian Müllner - -43.beta -======= -* Misc. bug fixes and cleanups [Florian; !237, !238] - -Contributors: - Florian Müllner - -Translators: - Nart Tlisha [ab] - -43.alpha -======== - -Contributors: - Florian Müllner - -Translators: - Marco Ciampa [it] - -42.3 -==== -* screenshot-window-sizer: Fix reported sizes on wayland [Florian; !232] -* window-list: Improve touch support [Florian; !233] - -Contributors: - Florian Müllner - -42.2 -==== -* native-window-placement: Adjust to gnome-shell 42 changes [Florian; !229] -* window-list: Fix visibility on non-primary monitors [Jason; !230] - -Contributors: - Jason Lynch, Florian Müllner - -Translators: - Cheng-Chia Tseng [zh_TW] - -42.1 -==== -* Misc. bug fixes and cleanups [Florian; !223, !222, !225] - -Contributors: - Florian Müllner - -Translators: - Milo Casagrande [it], Rūdolfs Mazurs [lv], Nathan Follens [nl], - Ngọc Quân Trần [vi], Zurab Kargareteli [ka] - -42.0 -==== - -Translators: - Philipp Kiemle [de], Balázs Úr [hu], Марко Костић [sr], sicklylife [ja], - Baurzhan Muftakhidinov [kk] - -42.rc -===== -* Misc. bug fixes and cleanups [Florian; !215, !218] - -Contributors: - Florian Müllner - -Translators: - Marek Černocký [cs], Dušan Kazik [sk], Piotr Drąg [pl], Jiri Grönroos [fi], - Luna Jernberg [sv], Alan Mortensen [da], Charles Monzat [fr], - Changwoo Ryu [ko] - -42.beta -======= -* workspace-indicator: Fix cancelling editing with Esc [Florian; !208] -* window-list: Update window tracking to avoid missing icons [Florian; !207] -* Use libadwaita for preferences [Florian; !209, !213] -* Adapt to Clutter grab API changes [Florian; !212] -* Misc. bug fixes and cleanups [Jan, Florian; !210, !214] - -Contributors: - Jan Beich, Florian Müllner, Naala Nanba - -Translators: - Boyuan Yang [zh_CN], Matej Urbančič [sl], Naala Nanba [ab], - Alexander Shopov [bg], Emin Tufan Çetin [tr] - -42.alpha -======== -* native-window-placement: Fix distorted layout in app grid [Sebastian; !189] -* window-list: Fix on-screen keyboard [Florian; !199] -* Misc. bug fixes and cleanups [Neal; Just; !195, !197] - -Contributors: - Piotr Drąg, Neal Gompa, Sebastian Keller, Florian Müllner, Just Perfection - -Translators: - Goran Vidović [hr], Sveinn í Felli [is], Yuri Chornoivan [uk], - Fabio Tomat [fur], Quentin PAGÈS [oc], Hugo Carvalho [pt], - Yaron Shahrabani [he], Jordi Mas i Hernandez [ca], MohammadSaleh Kamyab [fa], - Fran Dieguez [gl], Daniel Mustieles [es], Aleksandr Melman [ru], - Aurimas Černius [lt], Asier Sarasua Garmendia [eu], Kukuh Syafaat [id], - Rafael Fontenelle [pt_BR] - -41.0 -==== -* Bump version - -41.rc.1 -======= -* Fix pre-generating stylesheets in tarball [Florian; !190] - -Contributors: - Florian Müllner - -41.rc -===== -* window-list: Adapt to overview-on-startup [Florian; !185] -* apps-menu: Use a custom 'toggle-menu' shortcut [Florian; !173] -* Misc. bug fixes and cleanups [Florian; !186] - -Contributors: - Florian Müllner - -41.beta -======= -* window-list: Extend reactive area of minimap to screen edges [Adam; !171] -* drive-menu: Improve detection of network mounts [Florian; !27, !176] -* Use distinct gettext domain for e.g.o uploads [Florian; #335] -* Misc. bug fixes and cleanups [Florian; !172, !174, !177, !167, !178, !180, - !181, !182, !183] - -Contributors: - Marco Trevisan (Treviño), Adam Goode, Florian Müllner - -Translators: - Hugo Carvalho [pt], Juliano de Souza Camargo [pt], Alexander Shopov [bg] - -40.1 -==== -* Disable welcome dialog in classic session [Florian; !169] -* windowsNavigator: Adjust to a late gnome-shell change [Florian; !170] - -Contributors: - Florian Müllner - -Translators: - Ngọc Quân Trần [vi], Anders Jonsson [sv], Carmen Bianca BAKKER [eo], - Pawan Chitrakar [ne], Quentin PAGÈS [oc] - -40.0 -==== - -Translators: - Jiri Grönroos [fi] - -40.rc -===== -* native-window-placement: Adjust to gnome-shell changes [Florian; !164] -* windows-navigator: Adjust to gnome-shell changes [Florian; !163] -* window-list, workspace-indicator: Only show previews for up to six workspaces - [Florian; !165] -* window-list, workspace-indicator: Improve workspace preview appearance - [Florian; !166] - -Contributors: - Florian Müllner - -Translators: - Fran Dieguez [gl] - -40.beta -======= -* Add tooltips to workspace thumbnails [Florian; !155] -* Drop arrows from top bar menus [Florian; !156] -* drive-menu: Mark mounts that can be unmounted as removable [Michael; !152] -* Remove horizontal-workspaces extension [Florian; !158] -* Adjust to shell overview changes [Florian; !159, !160] -* Fix crashes [Daniel; !157] -* Misc. bug fixes and cleanups [Florian; !154, !161] - -Contributors: - Michael Lawton, Florian Müllner, Daniel van Vugt - -Translators: - Аляксей [be], A S Alam [pa] - -40.alpha.1 -========== -* Don't depend on sassc when building from tarball [Florian; !150] -* Port extensions preferences to GTK4 [Florian; !148] -* Misc. bug fixes and cleanups [Florian, Jonas; !149, !151, !153] - -Contributors: - Jonas Dreßler, Florian Müllner - -40.alpha -======== -* window-list: Honor changes in skip-taskbar property [Sergio; !130] -* window-list, workspace-indicator: Adjust to 3.38 changes [Florian; !133] -* window-list, workspace-indicator: Improve previews in workspace thumbs - [Florian; #260, !142] -* auto-move: Improve behavior on multi-monitor setups [Florian; !135] -* windowNavigator: Adjust to 3.38 changes [Thun; #259] -* Misc. bug fixes and cleanups [Florian, Jonas Å, Jordan, Ray; !131, !136, - !137, !140, !141, !144, !146, !145] - -Contributors: - Sergio Costas, Florian Müllner, Jordan Petridis, Thun Pin, Ray Strode, - Jonas Ådahl - -Translators: - Fabio Tomat [fur], Jordi Mas [ca] - -3.38.1 -====== - -Contributors: - Yacine Bouklif, Florian Müllner - -Translators: - Yacine Bouklif [kab], Cheng-Chia Tseng [zh_TW], Stas Solovey [ru], - Yosef Or Boczko [he] - -3.38.0 -====== - -Translators: - Balázs Meskó [hu], Alan Mortensen [da], Juliano Camargo [pt], Tim Sabsch [de], - Milo Casagrande [it], Rūdolfs Mazurs [lv] - -3.37.92 -======= - -Translators: - Nathan Follens [nl], Zander Brown [en_GB], Aurimas Černius [lt], - Marek Černocký [cs], Changwoo Ryu [ko], Dušan Kazik [sk] - -3.37.91 -======= - -Contributors: - Florian Müllner - -Translators: - Fran Dieguez [gl], Akarshan Biswas [bn_IN], Kukuh Syafaat [id], - Piotr Drąg [pl], Rafael Fontenelle [pt_BR], Jiri Grönroos [fi], - Марко Костић [sr], Goran Vidović [hr] - -3.37.90 -======= -* Misc. bug fixes and cleanups [Florian, Piotr; !126, !128] - -Contributors: - Piotr Drąg, Florian Müllner - -Translators: - Fabio Tomat [fur], Efstathios Iosifidis [el], Anders Jonsson [sv], - Asier Sarasua Garmendia [eu], Alexandre Franke [fr] - -3.37.3 -====== -* window-list, native-window-placement: Adjust to shell changes [Florian; !124] - -Contributors: - Florian Müllner - -Translators: - Jordi Mas [ca], sicklylife [ja], Boyuan Yang [zh_CN], - Baurzhan Muftakhidinov [kk] - -3.37.2 -====== -* window-list, auto-move: Modernize preference dialogs [Florian; !121] -* Adjust to gnome-shell changes [Florian; !122] - -Contributors: - Florian Müllner - -Translators: - Cheng-Chia Tseng [zh_TW], Yuri Chornoivan [uk], Daniel Mustieles [es], - Emin Tufan Çetin [tr], Danial Behzadi [fa], Daniel Șerbănescu [ro], - Matej Urbančič [sl] - -3.37.1 -====== -* drive-menu: Emphasize eject buttons [Florian; #223] -* user-theme: Add preference dialog [Florian; !117] -* window-list: Fix inconsistent state in preference dialog [Milan; !119] -* workspace-indicator: Overhaul preference dialog [Florian; !120] -* user-theme: Support session mode styles [Florian; !118] -* Misc. bug fixes and cleanups [Florian, Xiaoguang; !113, !106, !114, !116] - -Contributors: - Milan Crha, Florian Müllner, Xiaoguang Wang - -Translators: - Daniel Korostil [uk], Yosef Or Boczko [he], Kristjan SCHMIDT [eo], - Dz Chen [zh_CN], Danial Behzadi [fa], Yuri Chornoivan [uk], - Anders Jonsson [sv], Daniel Mustieles [es] - -3.36.0 -====== - -Contributors: - Florian Müllner - -3.35.91 -======= - -Contributors: - Florian Müllner - -Translators: - Zander Brown [en_GB] - -3.35.90 -======= -* Adjust to gnome-shell changes [Florian; !100, !101, !102] -* Force single-line window titles in window list [Florian; #202] -* Misc. bug fixes and cleanup [Florian; !104, !105] - -Contributors: - Florian Müllner - -Translators: - sicklylife [ja], Umarzuki Bin Mochlis Moktar [ms] - -3.35.3 -====== - -Translators: - Fran Dieguez [gl] - -3.35.2 -====== -* Adjust to gnome-shell changes [Marco, Florian; !89, !95, !96] -* window-list, workspace-indicator: Exclude DESKTOP windows from previews - [Florian; !93] -* screenshot-window-sizer: Fix cycling through all valid sizes [Willy; !97] - -Contributors: - Marco Trevisan (Treviño), Florian Müllner, Willy Stadnick - -3.34.1 -====== -* Adjust to gnome-settings-daemon plugin removals [Xiaoguang; !94] - -Contributors: - Florian Müllner, Xiaoguang Wang - -Translators: - Nathan Follens [nl], Dušan Kazik [sk], Ask Hjorth Larsen [da], - Yi-Jyun Pan [zh_TW] - -3.34.0 -====== - -Translators: - Rafael Fontenelle [pt_BR], Efstathios Iosifidis [el], Milo Casagrande [it], - Sabri Ünal [tr] - -3.33.92 -======= - -Translators: - Марко Костић [sr], Tim Sabsch [de], Rūdolfs Mazurs [lv], Matej Urbančič [sl], - Balázs Úr [hu], Claude Paroz [fr], Fran Dieguez [gl], Changwoo Ryu [ko], - Ryuta Fujii [ja], Fabio Tomat [fur], Goran Vidović [hr] - -3.33.91 -======= -* Misc. bug fixes and cleanups [Florian; !88, !90, !91, !92] - -Contributors: - Florian Müllner - -Translators: - Asier Sarasua Garmendia [eu], Anders Jonsson [sv], Marek Černocký [cs], - Kukuh Syafaat [id], Jiri Grönroos [fi], Florentina Mușat [ro], - Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl], Jordi Mas [ca], - Danial Behzadi [fa] -3.33.90 -======= -* window-list: Support showing windows from all workspaces [Florian; #154] -* Misc. bug fixes and cleanups [Florian; !86, !87] - -Contributors: - Florian Müllner - -Translators: - Jor Teron [mjw] - -3.33.4 -====== -* Make GNOME Classic more classic: - - Disable GNOME 3 overview [Florian; !69] - - Add window picker button to window list [Florian; !73, !80] - - Style improvements and fixes [Jakub; #169, !82] - - Support horizontal workspace layout in window list [Florian; !70] - - Add draggable previews to window list workspace switcher [Florian; !74] - - Arrange workspaces horizontally [Florian; !72] -* workspace-indicator: Support horizontal workspace layout [Florian; !71] -* workspace-indicator: Add draggable previews [Florian; !77] -* Misc. bug fixes and cleanups [Florian; !75, !76, !79, !78, #168, !84] - -Contributors: - Florian Müllner, Jakub Steiner, Jor Teron - -Translators: - Jor Teron [mjw] - -3.33.3 -====== -* Misc. bug fixes [Florian, Marco; !67, !68] - -Contributors: - Florian Müllner, Marco Trevisan (Treviño) - -3.33.2 -====== -* Misc. bug fixes and cleanups [Florian; !66] - -Contributors: - Florian Müllner - -3.33.1 -====== -* Misc. bug fixes [Florian; !64] - -Contributors: - Florian Müllner - -3.32.1 -====== -* Fix windowsNavigator extension after ES6 port [Florian; #143] -* screenshot-window-sizer: Add phone screenshot sizes [Adrien; !65] -* Misc. bug fixes and cleanups [Fabian; !62] - -Contributors: - Florian Müllner, Adrien Plazas, Fabian P. Schmidt - -3.32.0 -====== - -Contributors: - Florian Müllner - -Translations: - Victor Ibragimov [tg], Kristjan SCHMIDT [eo], Mart Raudsepp [et] - -3.31.92 -======= -* Misc. bug fixes and cleanups [Florian; !57, !58, !59, !60] - -Contributors: - Florian Müllner - -3.31.91 -======= -* apps-menu: Remove outdated legacy-tray handling [Florian; !53] -* user-theme: Allow using XDG user data dir [Tomasz; !55] -* Misc. bug fixes and cleanups [Florian; !52, !54, !56] - -Contributors: - Tomasz Gąsior, Florian Müllner - -Translators: - Matej Urbančič [sl], Gun Chleoc [gd] - -3.31.90 -======= -* Misc. bug fixes and cleanups [Florian; !49, !50, !51] - -Contributors: - Florian Müllner - -Translators: - Ryuta Fujii [ja], Charles Monzat [fr], Pieter Schalk Schoeman [af] - -3.31.2 -====== -* Remove obsolete alternate-tab extension [Florian; #786496] -* Adjust to gnome-shell changes [Florian; #113] - -Contributors: - Florian Müllner - -3.30.1 -====== -* apps-menu: Fix height on HiDPI systems [Florian; #102] -* window-list: Only switch between windows on active workspace when scrolling - [Florian; #78] - -Contributors: - Florian Müllner - -3.30.0 -====== -* Bump version - -3.29.91 -======= -* Misc. bug fixes [Florian; #90] - -Contributors: - Florian Müllner - -3.29.90 -======= -* Misc. bug fixes [Florian; #786496] - -Contributors: - Florian Müllner - -3.29.3 -====== -* Adjust to global.screen removal [Jonas; #759538] - -Contributors: - Jonas Ådahl, Florian Müllner - -3.29.2 -====== -* Misc. bug fixes [Florian; #69] - -Contributors: - Florian Müllner - -3.28.1 -====== -* Misc. bug fixes [Xiaoguang, Florian; #59, #62] - -Contributors: - Florian Müllner, Xiaoguang Wang - -Translators: - Dz Chen [zh_CN] - -3.28.0 -====== - -Contributors: - Florian Müllner, Xiaoguang Wang - -Translators: - Aman Alam [pa], Bruce Cowan [en_GB] - -3.27.92 -======= - -Contributors: - Florian Müllner - -Translators: - Piotr Drąg [es], GNOME Translation Robot [gd], Daniel Șerbănescu [ro] - -3.27.91 -======= -* places-menu: Support unmounting ejectable places [Rémy; #17] -* apps-menu: Support separators and custom sort order [Florian; #27] -* Port to meson [Florian; #31, #45] -* window-list: Fix missing icons on wayland [Florian; #10] -* places-menu: Fix terminating gnome-shell with recent gjs [Florian; #44] -* auto-move: Make it work with wayland windows [Florian; #33] -* Classic theme fixes [Florian, Jonas; #26, #41, #39, #40] -* Require sassc for classic styling [Florian; !28] -* Misc. bug fixes [Piotr, Florian; #772211, #32, #30] - -Contributors: - Jeremy Bicha, Piotr Drąg, Jonas Kümmerlin, Rémy Lefevre, Iñigo Martínez, - Florian Müllner - -Translators: - Matej Urbančič [sl], Kjartan Maraas [nb] - -3.27.1 -====== -* updated translations (ca@valencia) - -3.26.1 -====== -* native-window-placement: Adjust to gnome-shell changes -* updated translations: el, fa, ru, sv - -3.26.0 -====== -* updated translations (be, bg, ca, da, eu, fi, is, it, ko, lv, ml, - nl, pt_BR, vi, zh_TW) - -3.25.91 -======= -* updated translations (ca, fr, it, pl, pt_BR, sr, sr@latin, tr) - -3.25.90 -======= -* updated translations (es, gl, hr, hu, kk, sl, sv, sv) - -3.25.4 -====== -* screenshot-window-sizer: Fix backward cycling -* updated translations (ar, be, ca, cs, de, fur, id, lt, pl, sk) - -3.25.3 -====== -* places-menu: Use mount operation if necessary -* window-list: Respect MWM hints -* updated translations (es, fur, kk) - -3.25.2 -====== -* places-menu: Make URI launching asynchronous -* updated translations (de, fur, hr, hu, id, sl) - -3.25.1 -====== -* apps-menu: Mark copied launchers as trusted -* places-menu: Make icon lookup asynchronous -* updated translations (hr) - -3.24.1 -====== -* apps-menu: Allow creating desktop launchers via DND -* updated translations (el, vi) - -3.24.0 -====== -* updated translations (lv, tr) - -3.23.92 -======= -* update classic theme -* updated translations (be, ko, ca, da, cs, ru, lt) - -3.23.91 -======= -* updated translations (de, es, eu, fi, fr, fur, gl, hu, id, it, kk, nb, pl, pt_BR, - sk, sr, sr@latin, sv, uk, zh_TW) - -3.23.90 -======= -* window-list: Improve styling -* window-list: Hide workspace indicator when there's a single (static) workspace -* new translation (be) - -3.23.2 -====== -* alternateTab: Don't take over 'switch-group' shortcut -* updated translations (zh_CN) - -3.22.1 -====== -* window-list: Update icon on app changes - -3.22.0 -====== -* updated translations (en_GB) - -3.21.92 -======= -* update style -* updated translations (pl, vi) - -3.21.91 -======= -* updated translations (pl) - -3.21.90 -======= -* updated translations (es, gu) - -3.21.4 -====== -* apps-menu: Fix entries from non-standard AppDir directories - -3.21.3 -====== -* adjust to gnome-shell changes -* updated translations (oc) - -3.21.2 -====== -* version bump, nothing to see here - -3.20.1 -====== -* update classic style -* updated translations (gd, oc) - -3.20.0 -====== -* version bump, nothing to see here - -3.19.92 -======= -* version bump, nothing to see here - -3.19.91 -======= -* updated translations (oc) - -3.19.90 -======= -* version bump, nothing to see here - -3.19.4 -====== -* screenshot-window-sizer: HiDPI support -* Fix gnome-shell component in classic session -* updated translations (lt) - -3.19.3 -====== -* native-window-placement: Don't let border overlap title -* apps-menu: Fix handling of .desktop files in subdirectories -* updated translations (is) - -3.19.2 -====== -* updated translations (gd) - -3.19.1 -====== -* Fix some theme issues - -3.18.1 -====== -* window-list: Fix accessibility of window buttons -* apps-menu: Fix unreliable highlight -* updated translations (ar) - -3.18.0 -====== -* Bump version - -3.17.92 -======= -* places: Include DESKTOP when desktop icons are enabled -* updated translations (fa) - -3.17.91 -======= -* updated translations (nl, pl, zh_TW) - -3.17.90 -======= -* window-list: Improve application ordering -* workspace-indicator: Use consistent workspace numbering - -3.17.4 -====== -* updated translations (fur) - -3.17.3 -====== -* window-list: Adjust with text-scaling-factor -* classic style updates -* updated translations (pt, ro) - -3.17.2 -====== -* updated translations (oc, pt, zh_CN) - -3.17.1 -====== -* style updates -* updated translations (oc) - -3.16.1 -====== -* window-list: Fix workspace indicators popup menu position -* apps-menu: Fix taking over panel-main-menu shortcut -* updated translations (et, ja, lv) - -3.16.0 -====== -* updated translations (ca) - -3.15.92 -======= -* classic: Update theme -* update for mutter API changes -* updated translations (bg, bs, da, fi, pa, ru, sr, sr@latin, tg) - -3.15.91 -======= -* classic: Update theme -* systemMonitor extension was removed, as the message tray where it - put its indicator no longer exists -* window-list: Adjust for gnome-shell changes -* updated translations (gl, it, kk, ko, lt, pl, sk, uk, zh_TW) - -3.15.90 -======= -* classic: Visual refresh based on new shell theme -* window-list: Adjust for gnome-shell changes -* updated translations (an, el, eo, eu, fr, he, is, sv, tr) - -3.15.4 -====== -* window-list: Improve interaction with system modal dialogs -* updated translations (cs, de, es, eu, fur, hu, id, nb, pt_BR, ru, sl, vi) - -3.15.3.1 -======== -* adjust to gnome-shell change - -3.15.3 -====== -* classic-mode: Add high-contrast theme variant, drop .desktop file -* places-menu: Fix error when XDG user directories are not set up -* window-list: Add option to show on all monitors -* updated translations (eu, hu, kk, ro, tr) - -3.15.2 -====== -* removable-drive, user-theme, window-list: Update for gnome-shell changes -* apps-menu: Fix some visual glitches -* Fix classic mode style -* updated translations (an, cs, he, vi) - -3.15.1 -====== - * updated translations (es, nb) - -3.14.1 -====== - * alternateTab: Fix dismissing popup with Escape - * some improvements to the window-list - (spacing in app buttons, no flash when closing windows with auto-grouping) - * updated translations (lv, it, pt, bg) - -3.14.0 -====== - * updated translations (bn_IN, hi, kn, sr, sr@latin, uk) - -3.13.92 -======= -* new extension: screenshot-window-sizer -* window-list: Don't add sticky windows more than once -* updated translations (da, de, fi, ko, mr, ms, ne, pa, pl, sk, sv, ta, te, tr) - -3.13.91 -======= -* window-list: restore fitts'ability of workspace button -* updated for gnome-shell changes -* updated translations (cs, kk, fr, or, fa, ja, gu, id) - -3.13.90 -======= -* updated translations (as, ca, eu, nl, zh_CN, zh_HK, zh_TW) - -3.13.4 -====== -* Updated for gnome-shell changes -* updated translations (el, gl, ru) - -3.13.3 -====== -* Tweak preference UIs some more -* Fix classic mode schema overrides -* updated translations (es, he, hu, lt, nb, pt_BR, sl, tr) - -3.13.2 -====== -* Fix sorting of grouped buttons in window list -* Tweak preference UIs -* updated translations (en_GB) - -3.13.1 -====== -* add DesktopNames key to the classic session file -* classic theme: remove rounded corners from tile previews -* window-list: don't shift message tray on other monitors -* auto-move-windows: several fixes and updates for api changes -* launch-new-instances: updates for api changes -* updated translations (ja, km) - -3.12.0 -====== -* updated translations (zh_HK, zh_TW) - -3.11.92 -======= -* nothing to see here, move on - -3.11.91 -======= -* updated translations (ko, fur) - -3.11.90 -======= -* several fixes and improvements to the window-list - (can be scrolled, works correctly with the OSD - keyboard, filters skip-taskbar windows, does not - force all notifications to bold) -* drive-menu fixed not to show shadowed mounts -* updates for gnome-shell changes (launch-new-instance, - auto-move-windows, places-menu) -* build system fixes for systems without /bin/bash -* updated translations (or, tr, uk) - -3.11.5 -====== -* updates for gnome-shell changes -* updated translations (kn) - -3.11.4 -====== -* classic mode now supports session saving -* updates for gnome-shell changes -* updated translations (ar, kn) - -3.11.3 -====== -* workspace-indicator is vertically aligned now -* updated translations (ar, eo, ta, te) - -3.11.2 -====== -* updated translations (zh_CN) - -3.11.1 -====== -* ignore shadowed mounts in drive-menu extension -* updates for gnome-shell/gjs changes -* updated translations (el, th) - -3.10.1 -====== -* updated translations (af, ca, ca@valencia, de, et, eu, fa, - hu, lt, lv, nb, nl, pa, pt, sk, sr, sr@latin, tr) - -3.10.0 -====== -* updated translations (as, cs, da, es, et, fi, fr, gl, - he, id, it, kk, lt, lv, pa, pl, pt, pt_BR, ru, sl, tg, - uk, zh_HK, zh_TW) - -3.9.92 -====== -* more updates and fixes for gnome-shell master changes - and regressions (systemMonitor, window-list, apps-menu) -* lots of updated translations (ar, as, cs, da, de, el, es, - eu, fi, gl, he, hu, it, ja, kk, ko, lv, nb, nl, pa, pl, - pt_BR, ru, sk, sr, sr@latin, ta, tg) - -3.9.91 -====== -* update the classic mode session and theme to work with the - new system menu -* the usual round of updates and fixes for gnome-shell - API changes -* updated translations (de, it, lt, nl, pl, pt_BR, sk, - zh_HK, zh_TW) - -3.9.90 -====== -* xrandr-indicator was removed, as the implementation - was incompatible with the new DisplayConfig mutter API -* various extensions were updated for the 3.9.90 gnome-shell API -* updated translations (cs, es, fur, gl, he, hu, id, ja, sl, tg, - zh_CN, zh_HK, zh_TW) - -3.9.5 -===== -* alternative-status-menu was removed entirely, as - it does not fit in the designs of the new unified - status menu -* updated translations (as, gu, it, ru) - -3.9.4 -===== -* apps-menu: fixed handling of hot corner in case - of screen reconfiguration -* alternative-status-menu now correctly honors polkit - for hibernation -* user-menu now loads themes from $XDG_DATA_HOME too -* translation updates (de, id, pt_BR, vi, zh_CN, ml) - -3.9.3 -===== -* classic mode mini extensions were replaced with a - GSettings override specified in the .json file -* styling of classic mode improved -* native-window-placement is back working on 3.9 -* misc bug fixes -* traslation updates (an, cs, el, es, gl, nb, pl, sk, tg) - -3.9.2 -===== -* apps-menu: appearance of the scrollbars was improved -* window-list is a little taller in classic mode (to account - for the workspace switcher) -* alternative-status-menu honors again the dconf configuration -* translation updates (sr) - -3.9.1 -===== -* updates to window-list, xrandr-indicator, - workspace-indicator, windowsNavigator for gnome-shell - changes -* translation updates (cs, es, lt, pl, pt_BR, sl) - -3.8.1 -===== -* many improvements to window-list: - - windows are activated by DND over them - - window buttons now have the right size, - even if the text is smaller or larger - than the ideal - - window buttons can be grouped automatically - when the panel becomes crowded - - added a workspace switcher menu -* added keyboard navigation to apps-menu -* small tweaks to classic-mode theme, in particular - for menus -* translation updates (gl, ko, sr) - -3.8.0 -===== -* translation updates (hu, ja, fi, it) - -3.7.92 -====== -* misc bug fixes to app-menu and window-list -* translation updates (de, sl, pt_BR, ru) - -3.7.91 -====== -* various updates for shell changes -* update window-list to always use application icons -* update apps-menu to not load subdirectories as - separate categories -* translation updates (lt, zh_CN) - -3.7.90 -====== -* various fixes to make places-menu behave more - like Nautilus, including showing the machine - name in place of File System -* various updates for shell changes -* alternative-status-menu no longer supports - ConsoleKit systems, you need to install logind - to have suspend or hibernate -* translation updates (es, cz, pl, sr) - -3.7.5.1 -======= -* new extension forgotten in previous NEWS entry: - windows-list -* also forgotten previously: classic mode got a new - GNOME2 style -* build fixes - -3.7.5 -===== -* places-menu is back in the classic extensions, with - a new old GNOME-2 look -* classic mode moved the date menu to right, where we - all know it rightly belongs -* apps-menu received a face-lift, with the inclusion - of a reduced form of AxeMenu -* new extension in the classic set: launch-new-instance, - which modifies the behavior of clicking in the dash - and app launcher -* alternate-tab, native-window-placement and windowsNavigator - updated for gnome-shell changes -* translation updates (es, cz, pl) - -3.7.4 -===== -* a separate configure switch has been added to enable - classic mode session definitions -* places-menu is no longer part of the classic-mode - extension set -* updated translations (ar, gl, hu, lt, pt_BR, sr) - -3.7.3 -===== -* new extensions: default-min-max, static-workspaces -* alternate-tab now uses the built-in window switcher and just - takes over the switch-application keybinding -* workspace-indicator: is no longer part of classic-mode -* we now install classic-mode data files for gdm, gnome-session - and gnome-shell, so if you enable classic-mode you get a new - session option in GDM -* updated translations (ar, es, pl, ru, sl, zh_HK, zh_TW) - -3.7.2 -===== -* fixed crashes with places-menu, windowsNavigator, alternate-tab - and native-window-placement -* alternate-tab now hides attached modal dialogs -* places-menu has restored support for Nautilus 3.4 -* the default for hibernate is now to show in alternative-status-menu -* some extensions are now tagged as "classic", and can be chosen with - --enable-extensions=classic-mode -* dock and gajim were removed at the beginning of the 3.7.1 cycle, - as they were buggy and unmaintained -* updated translations (ar, cs, de, el, es, gl, id, lt, lv, pa, pl - ru, sk, sl, sr, sr@latin) - -3.6.1 -===== -* fixed alternative-status-menu for the new lock screen -* squashed some alternate-tab warnings -* drive-menu now works with 3.6 again -* updated translations (ar, cs, el, es, gl, id, lv, pl, sl) - -3.6.0 -===== -* major rework in places menu, to make it work without - removed supporting code in the shell and to make it look like - the nautilus sidebar - (similar work would be needed for drive-menu, not done yet) -* updated translations (ca, cs, de, el, en_GB, es, fi, hu, id, lt, - pl, pt_BR, ru, sl, sr) - -3.5.91 -====== -* various crashers were fixed in alternative-tab -* auto-move-windows now can be made to work with static workspaces -* place-menu is now on the left and uses symbolic icons like Files -* StIconType usage was removed from all extensions, after it was - removed in core -* systemMonitor, xrandr-indicator, apps-menu, places-menu, - alternative-status-menu were updated for the newer shell -* updated translations (es, gl, it, pl, sl) - -3.5.90 -====== -* alternate-tab has been reworked again, the old mode switch - was removed and the all&thumbnails code extended to handle - icons and filtering to the workspace -* alternate-tab thumbnails now reflect the aspect ratio of the windows -* systemMonitor now shows a tooltip above the indicator -* native-window-placement, systemMonitor and windowsNavigator have been updated - for the newer shell -* updated translations (es, pa) - -3.5.5 -===== -* convenience module has been relicensed to BSD, - for compatibility with GPLv3 extensions -* alternate-tab has been refactored and seen various - improvements to all&thumbnails mode, including a new - overlaid application icon -* updated translations (lt, id, sr) - -3.5.4 -===== -* updated translations (de, es, ar, sl, lv, zh_CN) - -3.5.2 -===== -* removable-drive-menu is now a11y friendly -* the dock can now be placed on any monitor, not just the primary -* dock is now clipped to its monitor -* alternative-status-menu now exposes GSettings for Suspend - and Hibernate visibility - no UI yet -* more gnome-shell API changes (places-menu, removable-drive-menu, - alternative-status-menu) -* miscellaneous bug fixes (native-window-placement, gajim, - auto-move-windows) -* updated translations - -3.4.0 -===== -* build system improvements -* updated translations (ar, cs, fr) - -3.3.92 -====== -* various updates for gnome-shell API changes (dock, - native-window-placement) -* local-install is now a make rule, not a shell script -* updated translations (zh, es, sw, ga, hu, it, no, pt_BR, de, sl, - pl, la, fi, sr) - -3.3.90 -====== -* system wide installation via "make install" is possible - again -* alternate-tab can now pre-activate the selected window -* auto-move-windows, workspace-indicator and example gained - new preference dialogs -* workspace-indicator: fixed a bug wrt focus stealing prevention -* updated translations (es, pt_BR, it, sl, gl, sr) - -3.3.5 -===== -* improvements to the build system and convenience module, - making it easier for other extensions to use, and bringing - it up to date with gnome-shell changes -* all extensions were ported to the Lang.Class framework - (except xrandr-indicator, which is pending GDBus merge) -* alternate-tab and dock were slightly refactored to clean up - some old code - -3.3.4 -===== -* improved styling of windowsNavigator tooltips -* fixed windowsNavigator when used with the numeric keypad -* fixed native-window-placement with custom button layout -* updated translations (pt_BR, cz) - -3.3.3 -===== -* windowsNavigator was fixed to work with azerty keyboards -* drive-menu was changed to use media-eject icon instead of media-optical -* dock: the default value of hide-effect is now move -* dock: if autohide is disabled, now it pushes maximized windows aside -* dock was updated to match current core shell styling -* native-window-placement: position stategy setting was removed -* alternative-status-menu no longer conflicts with other extensions - in the user menu -* various other minor bug fixes -* updated translations (zh, uk, es, it, cz, sl, sk, fi) - -3.3.2 -===== -* all extensions are now self-contained, including l10n and settings -* introduce a convenience module that can be shared among all extensions -* you can know build an installable zip file with make zip-file -* apps-menu no longer shows NoDisplay apps -* alternative-status-menu, alternate-tab: fix for master shell - -3.2.1 -===== -* dock: added "move" hide effect -* systemMonitor: now it enables/disables properly -* systemMonitor: improved styling -* alternate-tab: both modes now work with gnome-shell 3.2 -* various other bug fixes -* updated translations - -3.2.0 -===== - -* various: update for gnome-shell API changes - -3.1.91 -====== - -* gajim: update for gnome-shell API changes - -3.1.90 -====== - -* All extensions have been ported to the new extension - system (including live enable/disable) -* Updated translations -* xrandr-indicator no longer requires a specific gjs version -* windowsNavigator fixed for more than 2 workspaces - -3.1.4 -===== - -* New extension: a menu for changing workspace (workspace-indicator) -* systemMonitor: lower the requirement on libgtop -* auto-move-windows: open overview when last window on - last workspace is closed -* dock: implement autohiding, with various configurable - effects -* alternate-tab: more configurable implementations available -* native-window-placement: don't rearrange the windows when - the workspace switcher is shown/hidden -* update for gnome-shell 3.1.4 API changes - -3.1.3 -===== - -* New extension: a menu for removable drives (drive-menu -* New extensions: GNOME 2 like menus for apps and places - (apps-menu, places-menu) -* New extension: additional configurability for the window - layout in the overview, including a mechanism similar to - KDE4 (native-window-placement) -* New extension: a message tray indicator for CPU and memory - usage (uses libgtop) (systemMonitor) -* user-theme: fixed resetting theme -* user-theme: support themes installed in /usr/share/themes -* alternative-status-menu: ported to gnome-shell master -* dock: ported to gnome-shell master -* dock: make position configurable (can be left or right) -* Updated translations - -3.0.2 -===== - -* Updated translations. -* Fixed bug #647386 (reverting of user-theme to default) -* Fixed bug #647599 (support globally installed themes) -* Added license and README diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/extension.js deleted file mode 100755 index 1431878b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/extension.js +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-FileCopyrightText: 2011 Vamsi Krishna Brahmajosyula -// SPDX-FileCopyrightText: 2011 Giovanni Campagna -// SPDX-FileCopyrightText: 2013 Florian Müllner -// SPDX-FileCopyrightText: 2016 Rémy Lefevre -// -// SPDX-License-Identifier: GPL-2.0-or-later - -/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import St from 'gi://St'; - -import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; -import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; - -import {PlacesManager} from './placeDisplay.js'; - -const N_ = x => x; - -const PLACE_ICON_SIZE = 16; - -class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem { - static { - GObject.registerClass(this); - } - - constructor(info) { - super({ - style_class: 'place-menu-item', - }); - this._info = info; - - this._icon = new St.Icon({ - gicon: info.icon, - icon_size: PLACE_ICON_SIZE, - }); - this.add_child(this._icon); - - this._label = new St.Label({ - text: info.name, - x_expand: true, - y_align: Clutter.ActorAlign.CENTER, - }); - this.add_child(this._label); - - if (info.isRemovable()) { - this._ejectIcon = new St.Icon({ - icon_name: 'media-eject-symbolic', - style_class: 'popup-menu-icon', - }); - this._ejectButton = new St.Button({ - child: this._ejectIcon, - style_class: 'button', - }); - this._ejectButton.connect('clicked', info.eject.bind(info)); - this.add_child(this._ejectButton); - } - - info.connectObject('changed', - this._propertiesChanged.bind(this), this); - } - - activate(event) { - this._info.launch(event.get_time()); - - super.activate(event); - } - - _propertiesChanged(info) { - this._icon.gicon = info.icon; - this._label.text = info.name; - } -} - -const SECTIONS = [ - 'special', - 'devices', - 'bookmarks', - 'network', -]; - -class PlacesMenu extends PanelMenu.Button { - static { - GObject.registerClass(this); - } - - constructor() { - super(0.5, _('Places')); - - let label = new St.Label({ - text: _('Places'), - y_expand: true, - y_align: Clutter.ActorAlign.CENTER, - }); - this.add_child(label); - - this.placesManager = new PlacesManager(); - - this._sections = { }; - - for (let i = 0; i < SECTIONS.length; i++) { - let id = SECTIONS[i]; - this._sections[id] = new PopupMenu.PopupMenuSection(); - this.placesManager.connect(`${id}-updated`, () => { - this._redisplay(id); - }); - - this._create(id); - this.menu.addMenuItem(this._sections[id]); - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - } - } - - _onDestroy() { - this.placesManager.destroy(); - - super._onDestroy(); - } - - _redisplay(id) { - this._sections[id].removeAll(); - this._create(id); - } - - _create(id) { - let places = this.placesManager.get(id); - - for (let i = 0; i < places.length; i++) - this._sections[id].addMenuItem(new PlaceMenuItem(places[i])); - - this._sections[id].actor.visible = places.length > 0; - } -} - -export default class PlacesMenuExtension extends Extension { - enable() { - this._indicator = new PlacesMenu(); - - let pos = Main.sessionMode.panel.left.length; - if ('apps-menu' in Main.panel.statusArea) - pos++; - Main.panel.addToStatusArea('places-menu', this._indicator, pos, 'left'); - } - - disable() { - this._indicator.destroy(); - delete this._indicator; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ab/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ab/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 72dd7809..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ab/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/af/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/af/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 8df130b1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/af/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/an/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/an/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index f1966c09..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/an/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ar/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ar/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 1504827c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ar/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/as/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/as/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 103ee4fc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/as/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/be/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/be/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 70e79ec4..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/be/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bg/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bg/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 58fff19a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bg/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bn_IN/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bn_IN/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index ad967339..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bn_IN/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bs/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bs/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 6762b9a0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/bs/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ca/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ca/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index d1357900..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ca/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ca@valencia/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ca@valencia/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index ec53ac34..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ca@valencia/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/cs/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/cs/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index d4abcb5c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/cs/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/da/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/da/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index aa7bfc36..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/da/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/de/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/de/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 6d428b3e..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/de/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/el/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/el/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 94a3088e..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/el/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/en_GB/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/en_GB/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 6c0bdf76..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/en_GB/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/eo/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/eo/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index dc17d0e4..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/eo/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/es/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/es/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 627e131b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/es/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/et/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/et/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 5d3acdf1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/et/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/eu/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/eu/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 7ea42924..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/eu/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fa/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fa/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index afc6fbdc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fa/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fi/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fi/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index e1282ec2..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fi/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fr/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fr/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 75e20f2b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fr/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fur/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fur/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 82ab88ff..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/fur/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gd/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gd/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 278ecb75..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gd/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gl/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gl/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 9988bda1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gl/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gu/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gu/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 352f3ec7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/gu/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/he/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/he/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index fdac4596..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/he/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hi/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hi/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 0ff581fb..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hi/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hr/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hr/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 6bd83123..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hr/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hu/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hu/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 72e59b82..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/hu/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/id/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/id/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 0f39dc93..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/id/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/is/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/is/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 6b0cdb82..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/is/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/it/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/it/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 9a58492f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/it/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ja/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ja/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 2a895995..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ja/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ka/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ka/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index d3ca3887..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ka/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kab/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kab/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 7e2a8208..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kab/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kk/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kk/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 99958843..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kk/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/km/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/km/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index c0ce4976..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/km/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kn/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kn/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index a7cd0bfe..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/kn/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ko/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ko/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index abe5d13c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ko/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/lt/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/lt/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 77ed2e98..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/lt/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/lv/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/lv/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index fc3478f7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/lv/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/mjw/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/mjw/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 398469b0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/mjw/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ml/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ml/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index d3e6d6b6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ml/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/mr/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/mr/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index deb7e645..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/mr/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ms/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ms/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 8b713749..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ms/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/nb/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/nb/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 03d4fd5d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/nb/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ne/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ne/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index ae79bcad..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ne/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/nl/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/nl/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 2cf6641e..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/nl/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/oc/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/oc/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 6f7f771d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/oc/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/or/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/or/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index efd54bb9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/or/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pa/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pa/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 819a3438..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pa/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pl/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pl/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index b43077c9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pl/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pt/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pt/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 8b788871..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pt/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pt_BR/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pt_BR/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 1bb6d24d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/pt_BR/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ro/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ro/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 7b196533..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ro/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ru/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ru/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 513ee1cc..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ru/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sk/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sk/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index cd33006f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sk/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sl/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sl/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 873d92ee..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sl/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sr/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sr/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 651348d1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sr/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sr@latin/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sr@latin/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index d8496769..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sr@latin/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sv/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sv/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index ee7b5a6e..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/sv/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ta/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ta/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 4c9af822..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/ta/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/te/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/te/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 2d245ab5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/te/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/tg/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/tg/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 3fe68661..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/tg/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/th/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/th/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 34c2d934..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/th/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/tr/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/tr/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 92fd2ed5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/tr/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/uk/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/uk/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 00afbaef..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/uk/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/vi/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/vi/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 76c8af38..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/vi/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index d0763b15..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_CN/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_HK/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_HK/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 51bc4bfa..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_HK/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_TW/LC_MESSAGES/gnome-shell-extension-places-menu.mo b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_TW/LC_MESSAGES/gnome-shell-extension-places-menu.mo deleted file mode 100755 index 1b0f512a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/locale/zh_TW/LC_MESSAGES/gnome-shell-extension-places-menu.mo and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/metadata.json deleted file mode 100755 index 67e733a1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/metadata.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Add a menu for quickly navigating places in the system.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME's GitLab instance instead.", - "extension-id": "places-menu", - "gettext-domain": "gnome-shell-extension-places-menu", - "name": "Places Status Indicator", - "settings-schema": "org.gnome.shell.extensions.places-menu", - "shell-version": [ - "46" - ], - "url": "https://gitlab.gnome.org/GNOME/gnome-shell-extensions", - "uuid": "places-menu@gnome-shell-extensions.gcampax.github.com", - "version": 61 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/placeDisplay.js b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/placeDisplay.js deleted file mode 100755 index 930f92c6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/placeDisplay.js +++ /dev/null @@ -1,542 +0,0 @@ -// SPDX-FileCopyrightText: 2012 Giovanni Campagna -// SPDX-FileCopyrightText: 2013 Debarshi Ray -// SPDX-FileCopyrightText: 2015 Florian Müllner -// SPDX-FileCopyrightText: 2016 Rémy Lefevre -// SPDX-FileCopyrightText: 2017 Christian Kellner -// -// SPDX-License-Identifier: GPL-2.0-or-later - -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import Shell from 'gi://Shell'; -import {EventEmitter} from 'resource:///org/gnome/shell/misc/signals.js'; - -import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import * as ShellMountOperation from 'resource:///org/gnome/shell/ui/shellMountOperation.js'; - -const N_ = x => x; - -Gio._promisify(Gio.AppInfo, 'launch_default_for_uri_async'); -Gio._promisify(Gio.File.prototype, 'mount_enclosing_volume'); - -const BACKGROUND_SCHEMA = 'org.gnome.desktop.background'; - -const Hostname1Iface = ' \ - \ - \ - \ -'; -const Hostname1 = Gio.DBusProxy.makeProxyWrapper(Hostname1Iface); - -class PlaceInfo extends EventEmitter { - constructor(...params) { - super(); - - this._init(...params); - } - - _init(kind, file, name, icon) { - this.kind = kind; - this.file = file; - this.name = name || this._getFileName(); - this.icon = icon ? new Gio.ThemedIcon({name: icon}) : this.getIcon(); - } - - destroy() { - } - - isRemovable() { - return false; - } - - async _ensureMountAndLaunch(context, tryMount) { - try { - await Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(), context, null); - } catch (err) { - if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) { - Main.notifyError(_('Failed to launch “%s”').format(this.name), err.message); - return; - } - - let source = { - get_icon: () => this.icon, - }; - let op = new ShellMountOperation.ShellMountOperation(source); - try { - await this.file.mount_enclosing_volume(0, op.mountOp, null); - - if (tryMount) - this._ensureMountAndLaunch(context, false); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED)) - Main.notifyError(_('Failed to mount volume for “%s”').format(this.name), e.message); - } finally { - op.close(); - } - } - } - - launch(timestamp) { - let launchContext = global.create_app_launch_context(timestamp, -1); - this._ensureMountAndLaunch(launchContext, true); - } - - getIcon() { - this.file.query_info_async('standard::symbolic-icon', - Gio.FileQueryInfoFlags.NONE, - 0, - null, - (file, result) => { - try { - let info = file.query_info_finish(result); - this.icon = info.get_symbolic_icon(); - this.emit('changed'); - } catch (e) { - if (e instanceof Gio.IOErrorEnum) - return; - throw e; - } - }); - - // return a generic icon for this kind for now, until we have the - // icon from the query info above - switch (this.kind) { - case 'network': - return new Gio.ThemedIcon({name: 'folder-remote-symbolic'}); - case 'devices': - return new Gio.ThemedIcon({name: 'drive-harddisk-symbolic'}); - case 'special': - case 'bookmarks': - default: - if (!this.file.is_native()) - return new Gio.ThemedIcon({name: 'folder-remote-symbolic'}); - else - return new Gio.ThemedIcon({name: 'folder-symbolic'}); - } - } - - _getFileName() { - try { - let info = this.file.query_info('standard::display-name', 0, null); - return info.get_display_name(); - } catch (e) { - if (e instanceof Gio.IOErrorEnum) - return this.file.get_basename(); - throw e; - } - } -} - -class RootInfo extends PlaceInfo { - _init() { - super._init('devices', Gio.File.new_for_path('/'), _('Computer')); - - let busName = 'org.freedesktop.hostname1'; - let objPath = '/org/freedesktop/hostname1'; - new Hostname1(Gio.DBus.system, busName, objPath, (obj, error) => { - if (error) - return; - - this._proxy = obj; - this._proxy.connectObject('g-properties-changed', - this._propertiesChanged.bind(this), this); - this._propertiesChanged(obj); - }); - } - - getIcon() { - return new Gio.ThemedIcon({name: 'drive-harddisk-symbolic'}); - } - - _propertiesChanged(proxy) { - // GDBusProxy will emit a g-properties-changed when hostname1 goes down - // ignore it - if (proxy.g_name_owner) { - this.name = proxy.PrettyHostname || _('Computer'); - this.emit('changed'); - } - } - - destroy() { - this._proxy?.disconnectObject(this); - this._proxy = null; - super.destroy(); - } -} - - -class PlaceDeviceInfo extends PlaceInfo { - _init(kind, mount) { - this._mount = mount; - super._init(kind, mount.get_root(), mount.get_name()); - } - - getIcon() { - return this._mount.get_symbolic_icon(); - } - - isRemovable() { - return this._mount.can_eject() || this._mount.can_unmount(); - } - - eject() { - let unmountArgs = [ - Gio.MountUnmountFlags.NONE, - new ShellMountOperation.ShellMountOperation(this._mount).mountOp, - null, // Gio.Cancellable - ]; - - if (this._mount.can_eject()) { - this._mount.eject_with_operation(...unmountArgs, - this._ejectFinish.bind(this)); - } else { - this._mount.unmount_with_operation(...unmountArgs, - this._unmountFinish.bind(this)); - } - } - - _ejectFinish(mount, result) { - try { - mount.eject_with_operation_finish(result); - } catch (e) { - this._reportFailure(e); - } - } - - _unmountFinish(mount, result) { - try { - mount.unmount_with_operation_finish(result); - } catch (e) { - this._reportFailure(e); - } - } - - _reportFailure(exception) { - let msg = _('Ejecting drive “%s” failed:').format(this._mount.get_name()); - Main.notifyError(msg, exception.message); - } -} - -class PlaceVolumeInfo extends PlaceInfo { - _init(kind, volume) { - this._volume = volume; - super._init(kind, volume.get_activation_root(), volume.get_name()); - } - - launch(timestamp) { - if (this.file) { - super.launch(timestamp); - return; - } - - this._volume.mount(0, null, null, (volume, result) => { - volume.mount_finish(result); - - let mount = volume.get_mount(); - this.file = mount.get_root(); - super.launch(timestamp); - }); - } - - getIcon() { - return this._volume.get_symbolic_icon(); - } -} - -const DEFAULT_DIRECTORIES = [ - GLib.UserDirectory.DIRECTORY_DOCUMENTS, - GLib.UserDirectory.DIRECTORY_PICTURES, - GLib.UserDirectory.DIRECTORY_MUSIC, - GLib.UserDirectory.DIRECTORY_DOWNLOAD, - GLib.UserDirectory.DIRECTORY_VIDEOS, -]; - -export class PlacesManager extends EventEmitter { - constructor() { - super(); - - this._places = { - special: [], - devices: [], - bookmarks: [], - network: [], - }; - - this._settings = new Gio.Settings({schema_id: BACKGROUND_SCHEMA}); - this._settings.connectObject('changed::show-desktop-icons', - () => this._updateSpecials(), this); - this._updateSpecials(); - - /* - * Show devices, code more or less ported from nautilus-places-sidebar.c - */ - this._volumeMonitor = Gio.VolumeMonitor.get(); - this._volumeMonitor.connectObject( - 'volume-added', () => this._updateMounts(), - 'volume-removed', () => this._updateMounts(), - 'volume-changed', () => this._updateMounts(), - 'mount-added', () => this._updateMounts(), - 'mount-removed', () => this._updateMounts(), - 'mount-changed', () => this._updateMounts(), - 'drive-connected', () => this._updateMounts(), - 'drive-disconnected', () => this._updateMounts(), - 'drive-changed', () => this._updateMounts(), - this); - this._updateMounts(); - - this._bookmarksFile = this._findBookmarksFile(); - this._bookmarkTimeoutId = 0; - this._monitor = null; - - if (this._bookmarksFile) { - this._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null); - this._monitor.connect('changed', () => { - if (this._bookmarkTimeoutId > 0) - return; - /* Defensive event compression */ - this._bookmarkTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, 100, () => { - this._bookmarkTimeoutId = 0; - this._reloadBookmarks(); - return false; - }); - }); - - this._reloadBookmarks(); - } - } - - destroy() { - this._settings?.disconnectObject(this); - this._settings = null; - - this._volumeMonitor.disconnectObject(this); - - if (this._monitor) - this._monitor.cancel(); - if (this._bookmarkTimeoutId) - GLib.source_remove(this._bookmarkTimeoutId); - } - - _updateSpecials() { - this._places.special.forEach(p => p.destroy()); - this._places.special = []; - - let homePath = GLib.get_home_dir(); - - this._places.special.push(new PlaceInfo( - 'special', - Gio.File.new_for_path(homePath), - _('Home'))); - - let specials = []; - let dirs = DEFAULT_DIRECTORIES.slice(); - - if (this._settings.get_boolean('show-desktop-icons')) - dirs.push(GLib.UserDirectory.DIRECTORY_DESKTOP); - - for (let i = 0; i < dirs.length; i++) { - let specialPath = GLib.get_user_special_dir(dirs[i]); - if (!specialPath || specialPath === homePath) - continue; - - let file = Gio.File.new_for_path(specialPath), info; - try { - info = new PlaceInfo('special', file); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - continue; - throw e; - } - - specials.push(info); - } - - specials.sort((a, b) => GLib.utf8_collate(a.name, b.name)); - this._places.special = this._places.special.concat(specials); - - this.emit('special-updated'); - } - - _updateMounts() { - let networkMounts = []; - let networkVolumes = []; - - this._places.devices.forEach(p => p.destroy()); - this._places.devices = []; - this._places.network.forEach(p => p.destroy()); - this._places.network = []; - - /* Add standard places */ - this._places.devices.push(new RootInfo()); - this._places.network.push(new PlaceInfo( - 'network', - Gio.File.new_for_uri('network:///'), - _('Browse Network'), - 'network-workgroup-symbolic')); - - /* first go through all connected drives */ - let drives = this._volumeMonitor.get_connected_drives(); - for (let i = 0; i < drives.length; i++) { - let volumes = drives[i].get_volumes(); - - for (let j = 0; j < volumes.length; j++) { - let identifier = volumes[j].get_identifier('class'); - if (identifier && identifier.includes('network')) { - networkVolumes.push(volumes[j]); - } else { - let mount = volumes[j].get_mount(); - if (mount) - this._addMount('devices', mount); - } - } - } - - /* add all volumes that is not associated with a drive */ - let volumes = this._volumeMonitor.get_volumes(); - for (let i = 0; i < volumes.length; i++) { - if (volumes[i].get_drive()) - continue; - - let identifier = volumes[i].get_identifier('class'); - if (identifier && identifier.includes('network')) { - networkVolumes.push(volumes[i]); - } else { - let mount = volumes[i].get_mount(); - if (mount) - this._addMount('devices', mount); - } - } - - /* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */ - let mounts = this._volumeMonitor.get_mounts(); - for (let i = 0; i < mounts.length; i++) { - if (mounts[i].is_shadowed()) - continue; - - if (mounts[i].get_volume()) - continue; - - let root = mounts[i].get_default_location(); - if (!root.is_native()) { - networkMounts.push(mounts[i]); - continue; - } - this._addMount('devices', mounts[i]); - } - - for (let i = 0; i < networkVolumes.length; i++) { - let mount = networkVolumes[i].get_mount(); - if (mount) { - networkMounts.push(mount); - continue; - } - this._addVolume('network', networkVolumes[i]); - } - - for (let i = 0; i < networkMounts.length; i++) - this._addMount('network', networkMounts[i]); - - - this.emit('devices-updated'); - this.emit('network-updated'); - } - - _findBookmarksFile() { - let paths = [ - GLib.build_filenamev([GLib.get_user_config_dir(), 'gtk-3.0', 'bookmarks']), - GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']), - ]; - - for (let i = 0; i < paths.length; i++) { - if (GLib.file_test(paths[i], GLib.FileTest.EXISTS)) - return Gio.File.new_for_path(paths[i]); - } - - return null; - } - - _reloadBookmarks() { - this._bookmarks = []; - - let content = Shell.get_file_contents_utf8_sync(this._bookmarksFile.get_path()); - let lines = content.split('\n'); - - let bookmarks = []; - for (let i = 0; i < lines.length; i++) { - let line = lines[i]; - let components = line.split(' '); - let [bookmark] = components; - - if (!bookmark) - continue; - - let file = Gio.File.new_for_uri(bookmark); - if (file.is_native() && !file.query_exists(null)) - continue; - - let duplicate = false; - for (let j = 0; j < this._places.special.length; j++) { - if (file.equal(this._places.special[j].file)) { - duplicate = true; - break; - } - } - if (duplicate) - continue; - for (let j = 0; j < bookmarks.length; j++) { - if (file.equal(bookmarks[j].file)) { - duplicate = true; - break; - } - } - if (duplicate) - continue; - - let label = null; - if (components.length > 1) - label = components.slice(1).join(' '); - - bookmarks.push(new PlaceInfo('bookmarks', file, label)); - } - - this._places.bookmarks = bookmarks; - - this.emit('bookmarks-updated'); - } - - _addMount(kind, mount) { - let devItem; - - try { - devItem = new PlaceDeviceInfo(kind, mount); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - return; - throw e; - } - - this._places[kind].push(devItem); - } - - _addVolume(kind, volume) { - let volItem; - - try { - volItem = new PlaceVolumeInfo(kind, volume); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - return; - throw e; - } - - this._places[kind].push(volItem); - } - - get(kind) { - return this._places[kind]; - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/stylesheet.css deleted file mode 100755 index 2d7dbe3a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/places-menu@gnome-shell-extensions.gcampax.github.com/stylesheet.css +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020 Florian Müllner - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -.place-menu-item .button { - border-radius: 99px; - padding: 3px; - min-height: auto; -} - -.place-menu-item .button:ltr { margin-left: 6px; } -.place-menu-item .button:rtl { margin-right: 6px; } diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/extension.js deleted file mode 100644 index 55affab4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/extension.js +++ /dev/null @@ -1,45 +0,0 @@ -export var powerProfileIndicatorExtensionInstance; -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; -import * as Log from './modules/log.js'; -import * as Panel from './modules/panel.js'; -import * as Resources from './modules/resources.js'; -export default class PowerProfileIndicatorExtension extends Extension { - constructor(metadata) { - super(metadata); - this.PowerProfileIndicatorInstance = null; - this.systemMenu = null; - Resources.File.extensionPath = this.path; - powerProfileIndicatorExtensionInstance = this; - } - enable() { - this.systemMenu = Main.panel.statusArea.quickSettings; - if (!this.systemMenu) { - Log.raw("init", "system menu is not defined"); - return false; - } - if (this.systemMenu._powerProfiles) { - this.PowerProfileIndicatorInstance = new Panel.powerProfileIndicator(); - } - } - disable() { - if (this.PowerProfileIndicatorInstance) { - this.PowerProfileIndicatorInstance.stop(); - if (this.PowerProfileIndicatorInstance._indicator) - this.PowerProfileIndicatorInstance._indicator.destroy(); - this.PowerProfileIndicatorInstance._indicator = null; - this.PowerProfileIndicatorInstance.destroy(); - this.PowerProfileIndicatorInstance = null; - } - } - populate() { - if (this.PowerProfileIndicatorInstance !== null) { - if (this.systemMenu._system) - this.systemMenu._indicators.remove_child(this.systemMenu._system); - this.systemMenu._indicators.add_child(this.PowerProfileIndicatorInstance); - if (this.systemMenu._system) - this.systemMenu._indicators.add_child(this.systemMenu._system); - } - } -} -//# sourceMappingURL=extension.js.map \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/metadata.json deleted file mode 100644 index da199cd1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "a simple indicator in the system icons area of the top panel that represent the current power profile", - "name": "power-profile-indicator", - "shell-version": [ - "45", - "46" - ], - "url": "", - "uuid": "power-profile-indicator@laux.wtf", - "uuid-dev": "power-profile-indicator-dev@laux.wtf", - "version": 10 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/log.js b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/log.js deleted file mode 100644 index 355b2ead..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/log.js +++ /dev/null @@ -1,8 +0,0 @@ -export function raw(text = "", e = null) { - if (e !== null) - logError(e, `power-profile-indicator: ${text}`); - else { - log(`power-profile-indicator: ${text}`); - } -} -//# sourceMappingURL=log.js.map \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/panel.js b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/panel.js deleted file mode 100644 index 8c61cadd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/panel.js +++ /dev/null @@ -1,72 +0,0 @@ -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import * as quickSettings from 'resource:///org/gnome/shell/ui/quickSettings.js'; -import * as Log from './log.js'; -import * as Resources from './resources.js'; -import * as Extension from '../extension.js'; -const PROFILE_ICONS = { - "performance": "power-profile-performance-symbolic", - "balanced": "power-profile-balanced-symbolic", - "power-saver": "power-profile-power-saver-symbolic" -}; -export const powerProfileIndicator = GObject.registerClass(class powerProfileIndicator extends quickSettings.SystemIndicator { - constructor() { - super(...arguments); - this.powerProfilesProxy = null; - this.powerProfilesSignalProxy = null; - this.connected = false; - this._state = "balanced"; - this.profiles = []; - } - _init() { - super._init(); - this.createProxy(); - } - async createProxy() { - this._indicator = this._addIndicator(); - this._indicator.icon_name = "power-profile-balanced-symbolic"; - this._indicator.visible = true; - let xmlProfiles = Resources.File.DBus("net.hadess.PowerProfiles-0.10.1"); - this.powerProfilesProxy = await new Gio.DBusProxy.makeProxyWrapper(xmlProfiles)(Gio.DBus.system, "net.hadess.PowerProfiles", "/net/hadess/PowerProfiles", (proxy, e) => { - try { - this.connected = true; - if (this.updateProfile()) - Extension.powerProfileIndicatorExtensionInstance.populate(); - } - catch (error) { - Log.raw('could not get ActiveProfile', error); - } - }); - let xmlSignals = Resources.File.DBus("net.hadess.PowerProfilesSignals-0.10.1"); - this.powerProfilesSignalProxy = await new Gio.DBusProxy.makeProxyWrapper(xmlSignals)(Gio.DBus.system, "org.freedesktop.DBus.Properties", "/net/hadess/PowerProfiles", (proxy, e) => { - try { - proxy.connectSignal("PropertiesChanged", (name = "", variant, profile) => { - this.updateProfile(); - }); - } - catch (error) { - Log.raw('error creating signal', error); - } - }); - } - updateProfile() { - if (this.connected) - try { - this._state = this.powerProfilesProxy.ActiveProfile; - if (typeof this._state !== 'string') - return false; - this._indicator.icon_name = PROFILE_ICONS[this._state]; - return true; - } - catch (error) { - Log.raw("updateProfile", error); - } - return false; - } - stop() { - this.connected = false; - this.powerProfilesProxy = null; - this.powerProfilesSignalProxy = null; - } -}); -//# sourceMappingURL=panel.js.map \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/resources.js b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/resources.js deleted file mode 100644 index 77e7c6c8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/modules/resources.js +++ /dev/null @@ -1,17 +0,0 @@ -import GLib from 'gi://GLib'; -import * as Log from './log.js'; -export class File { - static DBus(name) { - let file = `${File.extensionPath}/resources/dbus/${name}.xml`; - try { - let [_ok, bytes] = GLib.file_get_contents(file); - if (!_ok) - Log.raw(`Couldn't read contents of "${file}"`); - return _ok ? imports.byteArray.toString(bytes) : null; - } - catch (e) { - Log.raw(`Failed to load "${file}"`, e); - } - } -} -//# sourceMappingURL=resources.js.map \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/resources/dbus/net.hadess.PowerProfiles-0.10.1.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/resources/dbus/net.hadess.PowerProfiles-0.10.1.xml deleted file mode 100644 index 67d1d038..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/resources/dbus/net.hadess.PowerProfiles-0.10.1.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/resources/dbus/net.hadess.PowerProfilesSignals-0.10.1.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/resources/dbus/net.hadess.PowerProfilesSignals-0.10.1.xml deleted file mode 100644 index bb6bda69..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/resources/dbus/net.hadess.PowerProfilesSignals-0.10.1.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/power-profile-indicator@laux.wtf/stylesheet.css deleted file mode 100644 index e69de29b..00000000 diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/CHANGELOG.md b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/CHANGELOG.md deleted file mode 100755 index 43fd941b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/CHANGELOG.md +++ /dev/null @@ -1,48 +0,0 @@ -## ROADMAP - -* add web search -* add unit conversion -* add currency conversion - -## release 15 - -* fix monitor preference - -## release 14 - -* port to gnome 45 -* remove blur background (permanently?) -* remove panel icon (temporarily?) - -## release 11 - -* fix close on enter/click - -## release 9 - -* add panel search icon -* fix close on escape - -## release 8 - -* fix follow cursor, preferred monitor - -## release 7 - -* improve background blurring -* add custom text color -* fix scroll issue -* fix fullscreen issue - -## release 5 - -* add window borders -* add background blur -* add font-size settings - -## release 4 - -* takes gnome's search outside of overview -* custom search window size -* bind to super+custom keys -* bind to preferred monitor or to cursor diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/LICENSE b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/LICENSE deleted file mode 100755 index a88e94d2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/LICENSE +++ /dev/null @@ -1,676 +0,0 @@ - Version 3, 29 June 2007 - - GNU GENERAL PUBLIC LICENSE - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/README.md b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/README.md deleted file mode 100755 index ff670e37..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/README.md +++ /dev/null @@ -1,62 +0,0 @@ -
-

-

Search Light

- -

- A GNOME Shell 42+ Extension -
-
-

-

- -[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/icedman) - -![Contributors](https://img.shields.io/github/contributors/icedman/search-light?color=dark-green) ![Forks](https://img.shields.io/github/forks/icedman/search-light?style=social) ![Stargazers](https://img.shields.io/github/stars/icedman/search-light?style=social) ![Issues](https://img.shields.io/github/issues/icedman/search-light) ![License](https://img.shields.io/github/license/icedman/search-light) - -![First Release](https://raw.githubusercontent.com/icedman/search-light/main/screenshots/Screenshot%20from%202022-11-03%2011-53-28.png) - - -This is a Gnome Shell extension that takes the apps search widget out of Overview. Like the macOS spotlight, or Alfred. - -### Notice - -* Gnome 46 port is ready for testing -* Gnome 45 port is ready for testing -* Gnome 44 and prior will be under g44 branch - -### Features - -* Popup search box -* Colors, background, borders customization -* Blurred background -* Multi-monitor support - -## Blurred background - -Blurred background feature requires **imagemagick** to be installed in the system which will generate the blurred image. - -### Installation - -Manual Installation: -- Clone this repo -```bash -$ git clone https://github.com/icedman/search-light -``` -- Use the `Makefile` to build and install -```bash -$ cd search-light -$ make -``` - -From Gnome Extensions Repository - -Visit [repository](https://extensions.gnome.org/extension/5489/search-light/) - -### Keybinding - -Ctrl+Cmd+Space (change at the preference page) -Cmd - your Windows logo, or the command logo on mac. Linux also calls this the 'Super' key. - -### Credits - -Blur-My-Shell for background blurring code. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/apps/org.gnome.Calculator.desktop b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/apps/org.gnome.Calculator.desktop deleted file mode 100755 index dc034d42..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/apps/org.gnome.Calculator.desktop +++ /dev/null @@ -1,251 +0,0 @@ -[Desktop Entry] -Name[af]=Sakrekenaar -Name[ar]=آلة حاسبة -Name[as]=গণক -Name[ast]=Calculadora -Name[az]=Hesaplayıcı -Name[be@latin]=Kalkulatar -Name[be]=Калькулятар -Name[bg]=Калкулатор -Name[bn_IN]=ক্যালকুলেটর -Name[bn]=ক্যালকুলেটর -Name[bs]=Računalo -Name[ca]=Calculadora -Name[ca@valencia]=Calculadora -Name[cs]=Kalkulačka -Name[cy]=Cyfrifiannell -Name[da]=Lommeregner -Name[de]=Taschenrechner -Name[dz]=རྩིས་འཕྲུལ། -Name[el]=Αριθμομηχανή -Name[en_CA]=Calculator -Name[en_GB]=Calculator -Name[en@shaw]=𐑒𐑨𐑤𐑒𐑿𐑤𐑱𐑑𐑼 -Name[eo]=Kalkulilo -Name[es]=Calculadora -Name[et]=Kalkulaator -Name[eu]=Kalkulagailua -Name[fa]=ماشین‌حساب -Name[fi]=Laskin -Name[fo]=Roknimaskina -Name[fr]=Calculatrice -Name[fur]=Calcoladorie -Name[ga]=Áireamhán -Name[gd]=Àireamhair -Name[gl]=Calculadora -Name[gu]=કૅલ્ક્યુલેટર -Name[he]=מחשבון -Name[hi]=गणक -Name[hr]=Kalkulator -Name[hu]=Számológép -Name[hy]=Հաշվիչ -Name[id]=Kalkulator -Name[it]=Calcolatrice -Name[ja]=電卓 -Name[ka]=კალკულატორი -Name[kk]=Калькулятор -Name[km]=ម៉ាស៊ីន​គិត​លេខ -Name[kn]=ಕ್ಯಾಲ್ಕುಲೇಟರ್ -Name[ko]=계산기 -Name[lt]=Skaičiuotuvas -Name[lv]=Kalkulators -Name[mai]=कैलकुलेटर -Name[mg]=Milina mpikajy -Name[mjw]=Calculator -Name[mk]=Калкулатор -Name[ml]=ഗണനി -Name[mn]=Тооны машин -Name[mr]=गणनयंत्र -Name[ms]=Kalkulator -Name[my]=ဂဏန်းတွက်စက် -Name[nb]=Kalkulator -Name[ne]=गणकयन्त्र -Name[nl]=Rekenmachine -Name[nn]=Kalkulator -Name[oc]=Calculadoira -Name[or]=କାଲକୁଲେଟର -Name[pa]=ਕੈਲਕੂਲੇਟਰ -Name[pl]=Kalkulator -Name[pt_BR]=Calculadora -Name[pt]=Calculadora -Name[ro]=Calculator -Name[ru]=Калькулятор -Name[si]=ගණකය -Name[sk]=Kalkulačka -Name[sl]=Računalo -Name[sq]=Makinë llogaritëse -Name[sr@latin]=Kalkulator -Name[sr]=Калкулатор -Name[sv]=Kalkylator -Name[ta]=கணிப்பான் -Name[te]=గణన పరికరం -Name[tg]=Калкулатор -Name[th]=เครื่องคิดเลข -Name[tk]=Çot -Name[tr]=Hesap Makinesi -Name[ug]=ھېسابلىغۇچ -Name[uk]=Калькулятор -Name[vi]=Máy tính bỏ túi -Name[xh]=Ikhaltyuleyitha -Name[zh_CN]=计算器 -Name[zh_HK]=計數機 -Name[zh_TW]=計算機 -Name=Calculator -Comment[af]=Voer rekenkundige, wetenskaplike of finansiële berekeninge uit -Comment[ar]=قم بحسابات رياضية , علمية و رياضية -Comment[as]=গণিতিক, বিজ্ঞানভিত্তিক অথবা আৰ্থিক গণনাসমূহ কৰক -Comment[ast]=Fai cálculos aritméticos, científicos o financieros -Comment[be]=Арыфметычныя, навуковыя і фінансавыя разлікі -Comment[bg]=Извършване на аритметични, научни или финансови изчисления -Comment[bn_IN]=গণিত, বৈজ্ঞানিক অথবা অর্থনৈতিক প্রণালী করুন -Comment[bn]=গাণিতিক, বৈজ্ঞানিক অথবা অর্থনৈতিক গণনা সম্পাদন করা হবে -Comment[bs]=Obavi aritmetičke, naučne ili finansijske proračune -Comment[ca]=Realitzeu càlculs aritmètics, científics o financers -Comment[ca@valencia]=Realitza càlculs aritmètics, científics o financers -Comment[cs]=Provádějte aritmetické, vědecké i finanční výpočty -Comment[da]=Udfør aritmetiske, videnskabelige eller finansielle udregninger -Comment[de]=Arithmetische, wissenschaftliche und finanztechnische Berechnungen durchführen -Comment[dz]=མཚན་རིགས་ དངུལ་འབྲེལ་ ཡང་ན་ ཨང་རྩིས་ཀྱི་ རྩིས་ལས་ཀྱི་ ལས་འགན་བསྒྲུབ་ -Comment[el]=Εκτελεί αριθμητικούς, επιστημονικούς ή εμπορικούς υπολογισμούς -Comment[en_CA]=Perform arithmetic, scientific or financial calculations -Comment[en_GB]=Perform arithmetic, scientific or financial calculations -Comment[en@shaw]=𐑐𐑼𐑓𐑹𐑥 𐑼𐑦𐑔𐑥𐑩𐑑𐑦𐑒, 𐑕𐑲𐑩𐑯𐑑𐑦𐑓𐑦𐑒 𐑹 𐑓𐑲𐑯𐑨𐑯𐑖𐑩𐑤 𐑒𐑨𐑤𐑒𐑿𐑤𐑱𐑖𐑩𐑯𐑟 -Comment[eo]=Fari aritmetikajn, sciencajn aŭ financajn kalkulojn -Comment[es]=Realice cálculos aritméticos, científicos o financieros -Comment[et]=Aritmeetilised, teaduslikud ja finantsarvutused -Comment[eu]=Egin kalkulu aritmetikoak, zientifikoak edo finantzarioak -Comment[fa]=انجام محاسبات ریاضی، علمی و مالی -Comment[fi]=Suorita aritmeettisia, tieteellisiä tai talouslaskutoimituksia -Comment[fo]=Avrika talfrøðiskar, vísindaligar ella fíggjarligar útrokningar -Comment[fr]=Effectue des calculs arithmétiques, scientifiques ou financiers -Comment[fur]=Eseguìs calcui aritmetics, sientifics o finanziaris -Comment[gd]=Dèan cunntadh àireamhachd, saidheansail no ionmhais -Comment[gl]=Realice cálculos aritméticos, científicos ou financeiros -Comment[gu]=ગાણિતીક, વૈજ્ઞાનિક અથવા આર્થિક ગણતરીઓ કરો -Comment[he]=ביצוע חישובים פשוטים, מדעיים או כלכליים -Comment[hi]=अंकगणित, वैज्ञानिक, या वित्तीय गणना करें -Comment[hr]=Izvodite aritmetičke, znanstvene ili financijske izračune -Comment[hu]=Aritmetikai, tudományos vagy pénzügyi számítások végrehajtása -Comment[hy]=Կատարել թվաբանական, գիտական կամ ֆինանսական հաշվարկներ -Comment[id]=Lakukan perhitungan aritmetik, ilmiah, atau keuangan -Comment[it]=Esegue calcoli aritmetici, scientifici o finanziari -Comment[ja]=算術/科学/財務の計算を行います -Comment[kk]=Қарапайым, ғылыми не қаржылық есептеулерді жүргізу -Comment[km]=អនុវត្ត​ការ​គណនា​គណិតវិទ្យា វិទ្យាសាស្ត្រ ឬ​ហិរញ្ញវត្ថុ -Comment[kn]=ಗಣಿತ, ವೈಜ್ಞಾನಿಕ ಅಥವಾ ಹಣಕಾಸಿನ ಲೆಕ್ಕಚಾರಗಳನ್ನು ಮಾಡಿ -Comment[ko]=일반 연산, 과학, 재무용 계산을 합니다 -Comment[lt]=Atlikti aritmetinius, mokslinius ar finansinius skaičiavimus -Comment[lv]=Veikt aritmētiskus, zinātniskus vai finansiālus aprēķinus -Comment[mjw]=Perform arithmetic, scientific or financial calculations -Comment[mk]=Извршете аритметички, научни или финансиски пресметки -Comment[ml]=അരിതമെറ്റിക്, ശാസ്ത്രീയം അല്ലെങ്കില്‍ ധനകാര്യ സംബന്ധമായ കണക്കുകൂട്ടലുകള്‍ നടത്തുക -Comment[mr]=अंकगणित, शास्त्रीय किंवा वित्तीय गणना चालवून पहा -Comment[ms]=Buat pengiraan aritmatik, saintifik dan kewangan -Comment[nb]=Utfør aritmetiske, vitenskapelige eller finansielle utregninger -Comment[ne]=अंकगणितीय, वैज्ञानिक वा आर्थिक गणनाहरू कार्यसम्पादन गर्नुहोस् -Comment[nl]=Voer rekenkundige, wetenschappelijke of financiële berekeningen uit -Comment[nn]=Utfør aritmetiske, vitskaplege eller finansielle utregningar -Comment[oc]=Efectua de calculs aritmetics, scientifics o financièrs -Comment[or]=ଗାଣିତିକ,ବୈଜ୍ଞାନିକ କିମ୍ବା ଆର୍ଥିକ ହିସାବ କରନ୍ତୁ -Comment[pa]=ਗਣਿਤ, ਵਿਗਿਆਨਕ ਜਾਂ ਵਿੱਤੀ ਗਣਨਾ ਕਰੋ -Comment[pl]=Wykonanie obliczeń arytmetycznych, naukowych lub finansowych -Comment[pt_BR]=Efetue cálculos aritméticos, científicos ou financeiros -Comment[pt]=Realize cálculos aritméticos, científicos ou financeiros -Comment[ro]=Efectuează calcule aritmetice, științifice și financiare -Comment[ru]=Вычисления: арифметические, научные и финансовые -Comment[sk]=Vykonáva aritmetické, vedecké alebo finančné výpočty -Comment[sl]=Izvajanje aritmetičnih, znanstvenih ali finančnih izračunov -Comment[sq]=Kryen llogari aritmetikore, shkencore ose financiare -Comment[sr@latin]=Izvršavajte aritmetičke, naučne ili finansijske proračune -Comment[sr]=Извршавајте аритметичке, научне или финансијске прорачуне -Comment[sv]=Utför aritmetiska, vetenskapliga eller finansiella beräkningar -Comment[ta]=கணித, அறிவியல் அல்லது பொருளாதார கணக்குகளை செய்கிறது. -Comment[te]=బీజీయ, శాస్త్రీయ లేదా ఆర్ధిక గణనలను ప్రదర్శించు -Comment[tg]=Иҷрои ҳисобҳои арифметикӣ, илмӣ ё молиявӣ -Comment[th]=คำนวณเลขคณิต ฟังก์ชันวิทยาศาสตร์ หรือการเงิน -Comment[tr]=Aritmetik, bilimsel ve finansal hesaplamalar gerçekleştirir -Comment[ug]=ئارىفمېتىكىلىق، ئىلمىي ياكى ئىقتىسادىي ھېساباتلارنى ئېلىپ بېرىش پروگراممىسى -Comment[uk]=Виконання арифметичних, наукових або фінансових розрахунків -Comment[vi]=Chạy phép tính kiểu số học, khoa học hay tài chính -Comment[zh_CN]=执行算术、科学或财务计算 -Comment[zh_HK]=進行數字、科學或金融的計算 -Comment[zh_TW]=進行數字、科學或財務計算 -Comment=Perform arithmetic, scientific or financial calculations -# Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! -Keywords[as]=গণনা;গণিতিক;বিজ্ঞানভিত্তিক;আৰ্থিক; -Keywords[be]=calculation;arithmetic;scientific;financial;вылічэнне;разлікі;арыфметыка;навука;фінансы; -Keywords[bg]=калкулатор;аритметични;научни;финансови;изчисления;calculation;arithmetic;scientific;financial; -Keywords[bn_IN]=গণনা;পাটিগণিত;বৈঞ্জানিক;অার্থিক; -Keywords[bs]=raču;aritmetika;naučni;finansijski; -Keywords[ca]=càlcul;aritmètic;científic;financer; -Keywords[ca@valencia]=càlcul;aritmètic;científic;financer; -Keywords[cs]=kalkulace;výpočty;vědecká;finanční; -Keywords[da]=udregning;aritmetik;videnskabelig;finansiel;regning;lommeregner;matematik; -Keywords[de]=Taschenrechner;Rechner;Arithmetisch;Wissenschaftlich;Finanztechnisch; -Keywords[el]=υπολογισμός;αριθμητικός;επιστημονικός;οικονομικός;calculation;arithmetic;scientific;financial; -Keywords[en_GB]=calculation;arithmetic;scientific;financial; -Keywords[eo]=kalkulilo;kalkuli;aritmetiko;scienca;financa; -Keywords[es]=cálculo;aritmética;científica;financiera; -Keywords[et]=arvutamine;arvutused;kalkuleerimine;kalkulaator;aritmeetika;teaduslik;finants; -Keywords[eu]=kalkulua;aritmetikoa;zientifikoa;finantzarioa; -Keywords[fa]=محاسبه;ریاضی;علمی;مالی; -Keywords[fi]=calculation;arithmetic;scientific;financial;laskenta;laskut;laskutoimitus;aritmetiikka;aritmeettinen;tieteellinen;tiede;talous;talouslaskut; -Keywords[fo]=útrokning;talfrøði;vísindaligur;fíggjarligur;rokning;lummaroknari;støddfrøði; -Keywords[fr]=calcul;arithmétique;scientifique;finances;financier; -Keywords[fur]=calcui;calcoladorie;aritmetic;sientific;finanziari; -Keywords[gd]=cunntadh;àireamhachadh;àireamhachd;saidheans;saidheansail;ionmhas;ionmhais; -Keywords[gl]=calculo;aritmético;científico;financeiro; -Keywords[gu]=ગણતરી;ગાણિતીક;વૈજ્ઞાનિક;આર્થિક; -Keywords[he]=חישוב;חשבון;מחשבון;מדעי;פיננסי; -Keywords[hi]=गणना; गणित; वैज्ञानिक; वित्तीय; -Keywords[hr]=izračuni;aritmetika;znanost;financije; -Keywords[hu]=számítás;aritmetikai;tudományos;pénzügyi; -Keywords[id]=kalkulasi;aritmetik;ilmiah;keuangan; -Keywords[it]=calcolo;calcolatrice;aritmetica;scientifica;finanziaria; -Keywords[ja]=calculation;arithmetic;scientific;financial;算術;科学;財務;calculator;計算機; -Keywords[kk]=calculation;arithmetic;scientific;financial;есептеу;калькулятор;арифметика;ғылыми;қаржылық; -Keywords[km]=អនុវត្ត​; ការ​គណនា​គណិតវិទ្យា; វិទ្យាសាស្ត្រ; ​ហិរញ្ញវត្ថុ; -Keywords[kn]=ಲೆಕ್ಕಾಚಾರ;ಅರಿತ್‌ಮೆಟಿಕ್;ವೈಜ್ಞಾನಿಕ;ಹಣಕಾಸು; -Keywords[ko]=calculation;계산;계산기;arithmetic;연산;scientific;과학;공학;financial;재무; -Keywords[lt]=skaičiavimai;aritmetika;moksliniai;finansiniai; -Keywords[lv]=aprēķins;aritmētika;zinātnisks;finansiāls; -Keywords[mjw]=calculation;arithmetic;scientific;financial; -Keywords[ml]=calculation;arithmetic;scientific;financial; -Keywords[mr]=कॅलक्युलेशन;अरिथमेटिक;साइंटिफिक;फाइनँशिअल; -Keywords[ms]=pengiraan;aritmatik;saintifik;kewangan; -Keywords[nb]=regning;aritmetikk,vitenskapelig;finans; -Keywords[ne]=अंकगणितीय;वैज्ञानिक;आर्थिक;गणनाहरू; -Keywords[nl]=calculation;arithmetic;scientific;financial;rekenkundig;wetenschappelijk;financieel; -Keywords[oc]=calcul;aritmetic;scientific;finances;financièr; -Keywords[or]=ହିସାବ;ଗାଣିତିକ;ବୈଜ୍ଞାନିକ;ଆର୍ଥିକ; -Keywords[pa]=ਗਣਨਾ;ਗਿਣਤੀ;ਹਿਸਾਬ;ਵਿਗਿਆਨਕ;ਵਿੱਤ;ਵਿੱਤੀ; -Keywords[pl]=obliczenia;liczenie;arytmetyczne;naukowe;finansowe; -Keywords[pt_BR]=cálculo;cálculos;aritmético;científico;científica;financeiro;financeira;aritmética; -Keywords[pt]=calcular;aritmética;científica;financeira; -Keywords[ro]=calculation;arithmetic;scientific;financial;calculare;aritmetic;științific;financiar;calculator; -Keywords[ru]=вычисление;арифметические;научные;финансовые; -Keywords[sk]=výpočty;aritmetické;vedecké;finančné; -Keywords[sl]=računanje;izračunavanje;aritmetika;znanstveni izračuni;finančni izračuni;računalo;kalkulator;abakus; -Keywords[sr@latin]=računanje;aritmetika;nauka;finansije;proračun; -Keywords[sr]=рачунање;аритметика;наука;финансије;прорачун; -Keywords[sv]=uträkning;aritmetik;vetenskaplig;finansiell; -Keywords[ta]=கணக்கிடுதல்;கணிதம்; அறிவியல்;பொருளாதாரம்; -Keywords[te]=calculation;arithmetic;scientific;financial; -Keywords[tg]=ҳисобкунӣ;арифметикӣ;илмӣ;молиявӣ; -Keywords[th]=คำนวณ;คิดเลข;เลขคณิต;วิทยาศาสตร์;การเงิน; -Keywords[tr]=hesaplama;aritmetik;bilimsel;finansal; -Keywords[ug]=calculation;arithmetic;scientific;financial;ھېسابلاش; -Keywords[uk]=калькулятор;арифметика;науковий;фінансовий; -Keywords[vi]=calculation;arithmetic;scientific;financial;bàn;tính;ban;tinh;toán;tài;chính;tai;chinh;khoa;học;hoc; -Keywords[zh_CN]=calculation;arithmetic;scientific;financial;计算;算术;科学;财务; -Keywords[zh_HK]=calculation;arithmetic;scientific;financial;科學;金融;計算; -Keywords[zh_TW]=calculation;arithmetic;scientific;financial;科學;金融;財務;計算;計算機;數字;數學;算數;算術;程式設計;單位轉換;轉換; -Keywords=calculation;arithmetic;scientific;financial; -Exec=gnome-calculator -# Translators: Do NOT translate or transliterate this text (this is an icon file name)! -Icon=org.gnome.Calculator -Terminal=false -Type=Application -StartupNotify=true -Categories=GNOME;GTK;Utility;Calculator; -X-Purism-FormFactor=Workstation;Mobile; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/blur_effect.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/blur_effect.glsl deleted file mode 100755 index 204f804a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/blur_effect.glsl +++ /dev/null @@ -1,41 +0,0 @@ -uniform sampler2D tex; -uniform float red; -uniform float green; -uniform float blue; -uniform float blend; -uniform vec2 textureSize; // Size of the texture being sampled - -// Function to perform a simple blur -vec4 blur(sampler2D texture, vec2 texCoord) { - vec4 sum = vec4(0.0); - float blurSize = 0.05; // Adjust this for different blur strengths - - // Sample neighboring pixels and average their colors - sum += texture2D(texture, texCoord + vec2(-blurSize, -blurSize)); - sum += texture2D(texture, texCoord + vec2(0.0, -blurSize)); - sum += texture2D(texture, texCoord + vec2(blurSize, -blurSize)); - sum += texture2D(texture, texCoord + vec2(-blurSize, 0.0)); - sum += texture2D(texture, texCoord); - sum += texture2D(texture, texCoord + vec2(blurSize, 0.0)); - sum += texture2D(texture, texCoord + vec2(-blurSize, blurSize)); - sum += texture2D(texture, texCoord + vec2(0.0, blurSize)); - sum += texture2D(texture, texCoord + vec2(blurSize, blurSize)); - - return sum / 9.0; // Adjust divisor for different blur strengths -} - -void main() { - vec2 texCoord = cogl_tex_coord_in[0].st; - vec4 original = texture2D(tex, texCoord); - - if (original.a >= 0.5) { - vec4 blurred = blur(tex, texCoord); - // blurred.a = original.a; - vec3 pix_color = blurred.rgb; - vec3 color = vec3(red * blurred.a, green * blurred.a, blue * blurred.a); - vec3 finalColor = mix(pix_color, color, blend * 0.75); - cogl_color_out = vec4(finalColor, (blurred.a + original.a)/2); - } else { - cogl_color_out = original; - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/blur_effect.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/blur_effect.js deleted file mode 100755 index 296c69e1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/blur_effect.js +++ /dev/null @@ -1,139 +0,0 @@ -'use strict'; - -import Shell from 'gi://Shell'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; - -const getTintShaderSource = (extensionDir) => { - const SHADER_PATH = GLib.build_filenamev([ - extensionDir, - 'effects', - 'blur_effect.glsl', - ]); - - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -export const BlurEffect = GObject.registerClass( - {}, - class SearchLighBlurEffect extends Clutter.ShaderEffect { - _init(params) { - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - this._static = true; - - // initialize without color as a parameter - - let _color = params.color; - delete params.color; - - super._init(params); - - // set shader color - - if (_color) this.color = _color; - } - - preload(path) { - // set shader source - this._source = getTintShaderSource(path); - if (this._source) this.set_shader_source(this._source); - - this.update_enabled(); - } - - get red() { - return this._red; - } - - set red(value) { - if (this._red !== value) { - this._red = value; - - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); - } - } - - get green() { - return this._green; - } - - set green(value) { - if (this._green !== value) { - this._green = value; - - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); - } - } - - get blue() { - return this._blue; - } - - set blue(value) { - if (this._blue !== value) { - this._blue = value; - - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); - } - } - - get blend() { - return this._blend; - } - - set blend(value) { - if (value > 0.5) { - value *= 0.75; - if (value < 0.5) { - value = 0.5; - } - } - if (this._blend !== value) { - this._blend = value; - - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); - } - this.update_enabled(); - } - - set color(rgba) { - let [r, g, b, a] = rgba; - this.red = r; - this.green = g; - this.blue = b; - this.blend = a; - } - - get color() { - return [this.red, this.green, this.blue, this.blend]; - } - - /// False set function, only cares about the color. Too hard to change. - set(params) { - this.color = params.color; - } - - update_enabled() { - this.set_enabled(this.blend > 0 && this._static); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value('tex', 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) super.vfunc_paint_target(paint_node); - else super.vfunc_paint_target(); - } - } -); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/color_effect.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/color_effect.glsl deleted file mode 100755 index 1a583b2b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/color_effect.glsl +++ /dev/null @@ -1,10 +0,0 @@ -uniform sampler2D tex; -uniform float red; -uniform float green; -uniform float blue; -uniform float blend; - -void main() { - vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); - cogl_color_out = vec4(red * c.a * blend, green * c.a * blend, blue * c.a * blend, c.a * blend); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/color_effect.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/color_effect.js deleted file mode 100755 index ff9a0db8..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/color_effect.js +++ /dev/null @@ -1,143 +0,0 @@ -// Adapted from from Blur-My-Shell - -'use strict'; - -import Shell from 'gi://Shell'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; - -const getColorEffectShaderSource = (extensionDir) => { - const SHADER_PATH = GLib.build_filenamev([ - extensionDir, - 'effects', - 'color_effect.glsl', - ]); - - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -/// New Clutter Shader Effect that simply mixes a color in, the class applies -/// the GLSL shader programmed into vfunc_get_static_shader_source and applies -/// it to an Actor. -/// -/// Clutter Shader Source Code: -/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c -/// -/// GJS Doc: -/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect -export const ColorEffect = GObject.registerClass( - {}, - class SearchLightColorShader extends Clutter.ShaderEffect { - _init(params) { - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - this._static = true; - - // initialize without color as a parameter - - let _color = params.color; - delete params.color; - - super._init(params); - - // set shader color - if (_color) this.color = _color; - } - - preload(path) { - // set shader source - this._source = getColorEffectShaderSource(path); - if (this._source) this.set_shader_source(this._source); - - this.update_enabled(); - } - - get red() { - return this._red; - } - - set red(value) { - if (this._red !== value) { - this._red = value; - - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); - } - } - - get green() { - return this._green; - } - - set green(value) { - if (this._green !== value) { - this._green = value; - - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); - } - } - - get blue() { - return this._blue; - } - - set blue(value) { - if (this._blue !== value) { - this._blue = value; - - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); - } - } - - get blend() { - return this._blend; - } - - set blend(value) { - if (this._blend !== value) { - this._blend = value; - - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); - } - this.update_enabled(); - } - - set color(rgba) { - let [r, g, b, a] = rgba; - this.red = r; - this.green = g; - this.blue = b; - this.blend = a; - } - - get color() { - return [this.red, this.green, this.blue, this.blend]; - } - - /// False set function, only cares about the color. Too hard to change. - set(params) { - this.color = params.color; - } - - update_enabled() { - this.set_enabled(this.blend > 0 && this._static); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value('tex', 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) super.vfunc_paint_target(paint_node); - else super.vfunc_paint_target(); - } - } -); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/easing.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/easing.js deleted file mode 100755 index e6aeb405..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/easing.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -/* PennerEasing */ -export const Linear = { - easeNone: (t, b, c, d) => { - return (c * t) / d + b; - }, - easeIn: (t, b, c, d) => { - return (c * t) / d + b; - }, - easeOut: (t, b, c, d) => { - return (c * t) / d + b; - }, - easeInOut: (t, b, c, d) => { - return (c * t) / d + b; - }, -}; - -export const Bounce = { - easeIn: (t, b, c, d) => { - return c - Bounce.easeOut(d - t, 0, c, d) + b; - }, - - easeOut: (t, b, c, d) => { - if ((t /= d) < 1 / 2.75) { - return c * (7.5625 * t * t) + b; - } else if (t < 2 / 2.75) { - let postFix = (t -= 1.5 / 2.75); - return c * (7.5625 * postFix * t + 0.75) + b; - } else if (t < 2.5 / 2.75) { - let postFix = (t -= 2.25 / 2.75); - return c * (7.5625 * postFix * t + 0.9375) + b; - } else { - let postFix = (t -= 2.625 / 2.75); - return c * (7.5625 * postFix * t + 0.984375) + b; - } - }, - - easeInOut: (t, b, c, d) => { - if (t < d / 2) return Bounce.easeIn(t * 2, 0, c, d) * 0.5 + b; - else return Bounce.easeOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; - }, -}; - -var Back = { - easeIn: (t, b, c, d) => { - let s = 1.70158; - let postFix = (t /= d); - return c * postFix * t * ((s + 1) * t - s) + b; - }, - - easeOut: (t, b, c, d) => { - let s = 1.70158; - return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; - }, - - easeInOut: (t, b, c, d) => { - let s = 1.70158; - if ((t /= d / 2) < 1) - return (c / 2) * (t * t * (((s *= 1.525) + 1) * t - s)) + b; - let postFix = (t -= 2); - return (c / 2) * (postFix * t * (((s *= 1.525) + 1) * t + s) + 2) + b; - }, -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/monochrome_effect.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/monochrome_effect.glsl deleted file mode 100755 index 6ac14478..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/monochrome_effect.glsl +++ /dev/null @@ -1,22 +0,0 @@ -uniform sampler2D tex; -uniform float red; -uniform float green; -uniform float blue; -uniform float blend; - -vec3 greyscale(vec3 color, float str) { - float g = dot(color, vec3(0.299, 0.587, 0.114)); - return mix(color, vec3(g), str); -} - -vec3 greyscale(vec3 color) { - return greyscale(color, 1.0); -} - -void main() { - vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); - vec3 pix_color = greyscale(c.rgb); - vec3 color = vec3(red * c.a, green * c.a, blue * c.a); - - cogl_color_out = vec4(mix(pix_color, color, blend), c.a); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/monochrome_effect.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/monochrome_effect.js deleted file mode 100755 index 35fb04bd..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/monochrome_effect.js +++ /dev/null @@ -1,150 +0,0 @@ -// Adapted from from Blur-My-Shell -// Adapted from https://gist.github.com/yiwenl/1c2ce935e66b82c7df5f - -'use strict'; - -import Shell from 'gi://Shell'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; - -const getMonochromeShaderSource = (extensionDir) => { - const SHADER_PATH = GLib.build_filenamev([ - extensionDir, - 'effects', - 'monochrome_effect.glsl', - ]); - - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -/// New Clutter Shader Effect that simply mixes a color in, the class applies -/// the GLSL shader programmed into vfunc_get_static_shader_source and applies -/// it to an Actor. -/// -/// Clutter Shader Source Code: -/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c -/// -/// GJS Doc: -/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect -export const MonochromeEffect = GObject.registerClass( - {}, - class SearchLightMonochromeEffect extends Clutter.ShaderEffect { - _init(params) { - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - this._static = true; - - // initialize without color as a parameter - - let _color = params.color; - delete params.color; - - super._init(params); - - // set shader color - if (_color) this.color = _color; - } - - preload(path) { - // set shader source - this._source = getMonochromeShaderSource(path); - if (this._source) this.set_shader_source(this._source); - - this.update_enabled(); - } - - get red() { - return this._red; - } - - set red(value) { - if (this._red !== value) { - this._red = value; - - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); - } - } - - get green() { - return this._green; - } - - set green(value) { - if (this._green !== value) { - this._green = value; - - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); - } - } - - get blue() { - return this._blue; - } - - set blue(value) { - if (this._blue !== value) { - this._blue = value; - - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); - } - } - - get blend() { - return this._blend; - } - - set blend(value) { - if (value > 0.5) { - value *= 0.75; - if (value < 0.5) { - value = 0.5; - } - } - if (this._blend !== value) { - this._blend = value; - - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); - } - this.update_enabled(); - } - - set color(rgba) { - let [r, g, b, a] = rgba; - this.red = r; - this.green = g; - this.blue = b; - this.blend = a; - } - - get color() { - return [this.red, this.green, this.blue, this.blend]; - } - - /// False set function, only cares about the color. Too hard to change. - set(params) { - this.color = params.color; - } - - update_enabled() { - this.set_enabled(this.blend > 0 && this._static); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value('tex', 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) super.vfunc_paint_target(paint_node); - else super.vfunc_paint_target(); - } - } -); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/tint_effect.glsl b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/tint_effect.glsl deleted file mode 100755 index c87c3ba1..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/tint_effect.glsl +++ /dev/null @@ -1,12 +0,0 @@ -uniform sampler2D tex; -uniform float red; -uniform float green; -uniform float blue; -uniform float blend; - -void main() { - vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); - vec3 pix_color = c.rgb; - vec3 color = vec3(red * c.a, green * c.a, blue * c.a); - cogl_color_out = vec4(mix(pix_color, color, blend), c.a); -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/tint_effect.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/tint_effect.js deleted file mode 100755 index 2f774a75..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/effects/tint_effect.js +++ /dev/null @@ -1,150 +0,0 @@ -// Adapted from from Blur-My-Shell - -'use strict'; - -import Shell from 'gi://Shell'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; - -const getTintShaderSource = (extensionDir) => { - const SHADER_PATH = GLib.build_filenamev([ - extensionDir, - 'effects', - 'tint_effect.glsl', - ]); - - try { - return Shell.get_file_contents_utf8_sync(SHADER_PATH); - } catch (e) { - console.log(`[d2dl] error loading shader from ${SHADER_PATH}: ${e}`); - return null; - } -}; - -/// New Clutter Shader Effect that simply mixes a color in, the class applies -/// the GLSL shader programmed into vfunc_get_static_shader_source and applies -/// it to an Actor. -/// -/// Clutter Shader Source Code: -/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c -/// -/// GJS Doc: -/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect -export const TintEffect = GObject.registerClass( - {}, - class SearchLightTintEffect extends Clutter.ShaderEffect { - _init(params) { - this._red = null; - this._green = null; - this._blue = null; - this._blend = null; - - this._static = true; - - // initialize without color as a parameter - - let _color = params.color; - delete params.color; - - super._init(params); - - // set shader color - - if (_color) this.color = _color; - } - - preload(path) { - // set shader source - this._source = getTintShaderSource(path); - if (this._source) this.set_shader_source(this._source); - - this.update_enabled(); - } - - get red() { - return this._red; - } - - set red(value) { - if (this._red !== value) { - this._red = value; - - this.set_uniform_value('red', parseFloat(this._red - 1e-6)); - } - } - - get green() { - return this._green; - } - - set green(value) { - if (this._green !== value) { - this._green = value; - - this.set_uniform_value('green', parseFloat(this._green - 1e-6)); - } - } - - get blue() { - return this._blue; - } - - set blue(value) { - if (this._blue !== value) { - this._blue = value; - - this.set_uniform_value('blue', parseFloat(this._blue - 1e-6)); - } - } - - get blend() { - return this._blend; - } - - set blend(value) { - if (value > 0.5) { - value *= 0.75; - if (value < 0.5) { - value = 0.5; - } - } - if (this._blend !== value) { - this._blend = value; - - this.set_uniform_value('blend', parseFloat(this._blend - 1e-6)); - } - this.update_enabled(); - } - - set color(rgba) { - let [r, g, b, a] = rgba; - this.red = r; - this.green = g; - this.blue = b; - this.blend = a; - } - - get color() { - return [this.red, this.green, this.blue, this.blend]; - } - - /// False set function, only cares about the color. Too hard to change. - set(params) { - this.color = params.color; - } - - update_enabled() { - this.set_enabled(this.blend > 0 && this._static); - } - - vfunc_paint_target(paint_node = null, paint_context = null) { - this.set_uniform_value('tex', 0); - - if (paint_node && paint_context) - super.vfunc_paint_target(paint_node, paint_context); - else if (paint_node) super.vfunc_paint_target(paint_node); - else super.vfunc_paint_target(); - } - } -); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/extension.js deleted file mode 100755 index 94425e85..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/extension.js +++ /dev/null @@ -1,939 +0,0 @@ -/* extension.js - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - */ - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; -import Clutter from 'gi://Clutter'; -import St from 'gi://St'; -import Graphene from 'gi://Graphene'; -import { trySpawnCommandLine } from 'resource:///org/gnome/shell/misc/util.js'; - -import { Timer } from './timer.js'; -import { Style } from './style.js'; - -import { TintEffect } from './effects/tint_effect.js'; -import { MonochromeEffect } from './effects/monochrome_effect.js'; -import { BlurEffect } from './effects/blur_effect.js'; - -import { schemaId, SettingsKeys } from './preferences/keys.js'; -import { KeyboardShortcuts } from './keybinding.js'; - -import { - Extension, - gettext as _, -} from 'resource:///org/gnome/shell/extensions/extension.js'; - -var SearchLight = GObject.registerClass( - {}, - class SearchLight extends St.Widget { - _init() { - super._init(); - this.name = 'searchLight'; - this.offscreen_redirect = Clutter.OffscreenRedirect.ALWAYS; - this.layout_manager = new Clutter.BinLayout(); - } - } -); - -const BLURRED_BG_PATH = '/tmp/searchlight-bg-blurred.jpg'; - -export default class SearchLightExt extends Extension { - enable() { - Main.overview.graphene = Graphene; - - this._style = new Style(); - - this._hiTimer = new Timer('hi-res timer'); - this._hiTimer.initialize(15); - - // for deferred or debounced runs - this._loTimer = new Timer('lo-res timer'); - this._loTimer.initialize(750); - - this._settings = this.getSettings(schemaId); - this._settingsKeys = SettingsKeys(); - - this._settingsKeys.connectSettings(this._settings, (name, value) => { - let n = name.replace(/-/g, '_'); - this[n] = value; - switch (name) { - case 'show-panel-icon': - if (this._indicator) { - this._indicator.visible = value; - } - break; - case 'background-color': - case 'blur-background': - this._updateBlurredBackground(); - this._updateCss(); - break; - case 'border-radius': - break; - case 'shortcut-search': - this._updateShortcut(); - break; - case 'secondary-shortcut-search': - this._updateShortcut2(); - break; - case 'window-effect': { - this._updateWindowEffect(); - break; - } - case 'window-effect-color': { - if (this.windowEffect) { - this.windowEffect.color = this.window_effect_color; - } - break; - } - } - }); - Object.keys(this._settingsKeys._keys).forEach((k) => { - let key = this._settingsKeys.getKey(k); - let name = k.replace(/-/g, '_'); - this[name] = key.value; - if (key.options) { - this[`${name}_options`] = key.options; - } - // console.log(`${name} ${key.value}`); - }); - - this._desktopSettings = new Gio.Settings({ - schema_id: 'org.gnome.desktop.background', - }); - this._desktopSettings.connectObject( - 'changed::picture-uri', - () => { - this._updateBlurredBackground(); - }, - this - ); - - this.mainContainer = new SearchLight(); - this.mainContainer._delegate = this; - this.container = new St.BoxLayout({ - name: 'searchLightBox', - vertical: true, - reactive: true, - track_hover: true, - can_focus: true, - }); - this.hide(); - this.container._delegate = this; - - Main.layoutManager.addChrome(this.mainContainer, { - affectsStruts: false, - affectsInputRegion: true, - trackFullscreen: false, - }); - - this.mainContainer.add_child(this.container); - - this._setupBackground(); - - this.accel = new KeyboardShortcuts(); - this.accel.enable(); - this.accel2 = new KeyboardShortcuts(); - this.accel2.enable(); - - this._updateShortcut(); - this._updateShortcut2(); - this._updateCss(); - - Main.overview.connectObject( - 'overview-showing', - this._onOverviewShowing.bind(this), - 'overview-hidden', - this._onOverviewHidden.bind(this), - this - ); - - Main.sessionMode.connectObject('updated', () => this.hide(), this); - - Shell.AppSystem.get_default().connectObject( - 'app-state-changed', - this._onAppStateChanged.bind(this), - this - ); - - global.display.connectObject( - 'window-created', - (display, win) => { - if (this._visible) { - this.mainContainer.opacity = 0; - } - }, - this - ); - - this._loTimer.runOnce(() => { - //this.show(); - // console.log('SearchLightExt: ???'); - }, 500); - - Main.overview.searchLight = this; - - let appInfo = Gio.DesktopAppInfo.new_from_filename( - `${this.path}/apps/org.gnome.Calculator.desktop` - ); - - let _providers = []; - - // deferred startup for providers - let idx = 0; - _providers.forEach((p) => { - this._loTimer.runOnce(() => { - p.initialize(); - }, idx * 5000); - }); - - this._loTimer.runOnce(() => { - this._createIndicator(); - }, 1500); - this._updateProviders(); - this._updateWindowEffect(); - this._updateBlurredBackground(); - } - - disable() { - this._hiTimer?.shutdown(); - this._loTimer?.shutdown(); - this._hiTimer = null; - this._loTimer = null; - - if (this._indicator) { - this._indicator.disconnectObject(this); - if (this._indicator.get_parent()) { - this._indicator.get_parent().remove_child(this._indicator); - } - this._indicator = null; - } - - this._style.unloadAll(); - this._style = null; - - this._settingsKeys.disconnectSettings(); - this._settings = null; - - this._desktopSettings.disconnectObject(); - this._desktopSettings = null; - - if (this.accel) { - this.accel.disable(); - delete this.accel; - this.accel = null; - } - if (this.accel2) { - this.accel2.disable(); - delete this.accel2; - this.accel2 = null; - } - - this._removeProviders(); - this._providers = null; - - Main.layoutManager.removeChrome(this.mainContainer); - this.mainContainer = null; - } - - _createIndicator() { - if (this._indicator) return; - this._indicator = new St.Button({ - style_class: 'panel-status-indicators-box', - }); - let icon = new St.Icon({ - gicon: new Gio.ThemedIcon({ name: 'search-symbolic' }), - }); - icon.style = 'margin-top: 6px !important; margin-bottom: 6px !important;'; - this._indicator.set_child(icon); - this._indicator.connectObject( - 'button-press-event', - this._toggle_search_light.bind(this), - this - ); - try { - Main.panel._rightBox.insert_child_at_index(this._indicator, 0); - this._indicator.visible = this.show_panel_icon; - } catch (err) { - console.log(err); - } - } - - _createEffect(idx) { - let effect = null; - switch (idx) { - case 1: { - effect = new TintEffect({ - name: 'color', - color: this.window_effect_color, - }); - effect.preload(this.path); - break; - } - case 2: { - effect = new MonochromeEffect({ - name: 'color', - color: this.window_effect_color, - }); - effect.preload(this.path); - break; - } - case 3: { - effect = new BlurEffect({ - name: 'color', - color: this.window_effect_color, - }); - effect.preload(this.path); - break; - } - } - return effect; - } - - _updateBlurredBackground() { - this.desktop_background = this._desktopSettings.get_string('picture-uri'); - this.desktop_background_blurred = BLURRED_BG_PATH; - if (this.blur_background) { - // let color = this.background_color || [0, 0, 0, 0.5]; - // let bg = this._desktopSettings.get_string('picture-uri'); - // let a = Math.floor(100 - color[3] * 100); - // let rgb = this._style.hex(color); - // let cmd = `convert -scale 10% -blur 0x2.5 -resize 200% -fill "${rgb}" -tint ${a} "${bg}" ${BLURRED_BG_PATH}`; - let cmd = `convert -scale 10% -blur 0x2.5 -resize 200% "${this.desktop_background}" ${BLURRED_BG_PATH}`; - console.log(cmd); - trySpawnCommandLine(cmd); - } - } - - _updateWindowEffect() { - // this.window_effect = 2; - // this.window_effect_color = [1, 0, 0, 0.5]; - this.container.remove_effect_by_name('window-effect'); - let effect = this._createEffect(this.window_effect); - if (effect) { - this.container.add_effect_with_name('window-effect', effect); - } - this.windowEffect = effect; - } - - _updatePanelIcon(disable) {} - - _updateProviders() { - this._removeProviders(); - this._providers = []; - - let _search = Main.overview.searchController; - if (!_search) return; - - // add providers here - - if (_search.addProvider) { - this._providers.forEach((p) => { - _search.addProvider(p); - }); - } - } - - _removeProviders() { - if (!this._providers) { - return; - } - - let _search = Main.overview.searchController; - if (!_search) return; - - if (_search.removeProvider) { - this._providers.forEach((p) => { - _search.removeProvider(p); - }); - } - - this._providers = null; - } - - _setupBackground() { - if (this._background && this._background.get_parent()) { - this._background.get_parent().remove_child(this._background); - } - - // blurred background image - // this._bgActor = new Meta.BackgroundActor(); - // let bgSource = Main.layoutManager._backgroundGroup.get_child_at_index(0); - // this._bgActor.set_content(bgSource.get_content()); - // this._blurEffect = new Shell.BlurEffect({ - // name: 'blur', - // brightness: this.blur_brightness, - // sigma: this.blur_sigma, - // mode: Shell.BlurMode.ACTOR, - // }); - - if (!this._blurEffect) { - this._blurEffect = this._createEffect(1); - } - - let background = new St.Widget({ - name: 'searchLightBlurredBackground', - layout_manager: new Clutter.BinLayout(), - x: 0, - y: 0, - width: 20, - height: 20, - }); - - // let image = new St.Widget({ - // name: 'searchLightBlurredBackgroundImage', - // x: 0, - // y: 0, - // width: 20, - // height: 20, - // effect: this._blurEffect, - // }); - - // image.add_child(this._bgActor); - // background.add_child(image); - // this._bgActor.clip_to_allocation = true; - // this._bgActor.offscreen_redirect = Clutter.OffscreenRedirect.ALWAYS; - - this.mainContainer.insert_child_below(background, this.container); - this._background = background; - this._background.opacity = 0; - this._background.visible = false; - } - - show() { - if (Main.overview.visible) return; - - this._acquire_ui(); - - if (this._bgActor) { - let bgSource = Main.layoutManager._backgroundGroup.get_child_at_index(0); - this._bgActor.set_content(bgSource.get_content()); - } - - this.mainContainer.opacity = 0; - this._updateCss(); - this._layout(); - this.mainContainer.show(); - this.container.show(); - - // fixes the background size relative to text - after adjusting font size - this._hiTimer.runOnce(() => { - this.mainContainer.opacity = 255; - this._layout(); - }, 100); - - this._add_events(); - - Meta.disable_unredirect_for_display(global.display); - } - - hide() { - this._visible = false; - this._release_ui(); - this._remove_events(); - this.mainContainer.hide(); - // this._hidePopups(); - - Meta.enable_unredirect_for_display(global.display); - } - - _layout() { - this._queryDisplay(); - if (!this.monitor) return; - - // container size - this.width = - 600 + ((this.sw * this.scaleFactor) / 2) * (this.scale_width || 0); - this.height = - 400 + ((this.sh * this.scaleFactor) / 2) * (this.scale_height || 0); - - // initial height - let font_size = 14; - if (this.font_size) { - font_size = this.font_size_options[this.font_size]; - } - if (this.entry_font_size) { - font_size = this.entry_font_size_options[this.entry_font_size]; - } - - // let padding = { - // 14: 14 * 2.5, - // 16: 16 * 2.4, - // 18: 18 * 2.2, - // 20: 20 * 2.0, - // 22: 22 * 1.8, - // 24: 24 * 1.6, - // }; - // this.initial_height = padding[font_size] * this.scaleFactor; - // this.initial_height += font_size * 2 * this.scaleFactor; - // console.log(`${this.initial_height} ${this._entry.height}`); - - this.initial_height = this._entry.height + 4 * this.scaleFactor; - - // position - let x = this.monitor.x + this.sw / 2 - this.width / 2; - let y = this.monitor.y + this.sh / 2 - this.height / 2; - this._visible = true; - - this.container.set_size(this.width, this.initial_height); - this.mainContainer.set_size(this.width, this.initial_height); - this.mainContainer.set_position(x, y); - - // background - if (this._background) { - if (this._bgActor) { - this._bgActor.set_position(this.monitor.x - x, this.monitor.y - y); - this._bgActor.set_size(this.monitor.width, this.monitor.height); - this._bgActor - .get_parent() - .set_size(this.monitor.width, this.monitor.height); - } - let padding = 0; //this.border_thickness || 0; - this._background.set_position(padding, padding); - this._background.set_size( - this.monitor.width - padding * 2, - this.monitor.height - padding * 2 - ); - } - } - - _updateShortcut(disable) { - this.accel.unlisten(); - - let shortcut = ''; - try { - shortcut = (this.shortcut_search || []).join(''); - } catch (err) { - // - } - if (shortcut == '') { - shortcut = 'Space'; - } - - if (!disable) { - this.accel.listenFor(shortcut, this._toggle_search_light.bind(this)); - } - } - - _updateShortcut2(disable) { - this.accel2.unlisten(); - - let shortcut = ''; - try { - shortcut = (this.secondary_shortcut_search || []).join(''); - } catch (err) { - // - } - if (shortcut == '') { - shortcut = 'Space'; - } - - if (!disable) { - this.accel2.listenFor(shortcut, this._toggle_search_light.bind(this)); - } - } - - _queryDisplay() { - let idx = this.preferred_monitor || 0; - if (idx == 0) { - idx = Main.layoutManager.primaryIndex; - } else if (idx == Main.layoutManager.primaryIndex) { - idx = 0; - } - this.monitor = - Main.layoutManager.monitors[idx] || Main.layoutManager.primaryMonitor; - - if (this.popup_at_cursor_monitor) { - let pointer = global.get_pointer(); - Main.layoutManager.monitors.forEach((m) => { - if ( - pointer[0] >= m.x && - pointer[0] <= m.x + m.width && - pointer[1] >= m.y && - pointer[1] <= m.y + m.height - ) { - this.monitor = m; - } - }); - } - - this.sw = this.monitor.width; - this.sh = this.monitor.height; - - if (this._last_monitor_count != Main.layoutManager.monitors.length) { - this._settings.set_int( - 'monitor-count', - Main.layoutManager.monitors.length - ); - this._last_monitor_count = Main.layoutManager.monitors.length; - } - } - - _acquire_ui() { - if (this._entry) return; - - if (!Main.overview._toggle) { - Main.overview._toggle = Main.overview.toggle; - } - Main.overview.toggle = () => { - if (this._search && this._search.visible) { - this._search._text.get_parent().grab_key_focus(); - } - }; - if (!Main.overview._hide) { - Main.overview._hide = Main.overview.hide; - } - Main.overview.hide = () => { - this.mainContainer.opacity = 0; - Main.overview._hide(); - }; - - this._queryDisplay(); - - this.scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - - this._entry = Main.overview.searchEntry; - this._entryParent = this._entry.get_parent(); - this._entry.add_style_class_name('slc'); - - this._search = Main.overview.searchController; - - this._search.hide(); - this._searchResults = this._search._searchResults; - this._searchParent = this._search.get_parent(); - - if (!this._searchResults._activateDefault) { - this._searchResults._activateDefault = - this._searchResults.activateDefault; - } - this._searchResults.activateDefault = () => { - // hide window immediately when activated - this.mainContainer.opacity = 0; - this._searchResults._activateDefault(); - }; - - if (this._entry.get_parent()) { - this._entry.get_parent().remove_child(this._entry); - } - this.container.add_child(this._entry); - if (this._search.get_parent()) { - this._search.get_parent().remove_child(this._search); - } - this.container.add_child(this._search); - if (!this._search.__searchCancelled) { - this._search.__searchCancelled = this._search._searchCancelled; - this._search._searchCancelled = () => {}; - } - this._search._text.get_parent().grab_key_focus(); - this._textChangedEventId = this._search._text.connect( - 'text-changed', - () => { - this.container.set_size(this.width, this.height); - this.mainContainer.set_size(this.width, this.height); - if (this._corners) { - this._corners[2].y = this.height - this._corners[1].height; - this._corners[3].y = this.height - this._corners[1].height; - this._edges[3].y = this.height - 2; - } - this._search.show(); - } - ); - - this._search._text.get_parent().grab_key_focus(); - } - - _release_ui() { - if (this._entry) { - this._entry.get_parent().remove_child(this._entry); - this._entryParent.add_child(this._entry); - this._entry = null; - } - - if (this._search) { - this._removeProviders(); - this._search.hide(); - this._search.get_parent().remove_child(this._search); - this._searchParent.add_child(this._search); - if (this._textChangedEventId) { - this._search._text.disconnect(this._textChangedEventId); - this._textChangedEventId = null; - } - if (this._search.__searchCancelled) { - this._search._searchCancelled = this._search.__searchCancelled; - this._search.__searchCancelled = null; - } - this._search = null; - - if (this._searchResults._activateDefault) { - this._searchResults.activateDefault = - this._searchResults._activateDefault; - this._searchResults._activateDefault = null; - } - } - - if (Main.overview._toggle) { - Main.overview.toggle = Main.overview._toggle; - Main.overview._toggle = null; - } - if (Main.overview._hide) { - Main.overview.hide = Main.overview._hide; - Main.overview._hide = null; - } - } - - _updateCss(disable) { - let bg = this.background_color || [0, 0, 0, 0.5]; - if (this.text_color && this.text_color[3] > 0) { - this.container.remove_style_class_name('light'); - } else { - if (0.3 * bg[0] + 0.59 * bg[1] + 0.11 * bg[2] < 0.5) { - this.container.remove_style_class_name('light'); - } else { - this.container.add_style_class_name('light'); - } - } - - this._background.remove_effect_by_name('blur'); - if (this._blurEffect && this.blur_background) { - this._background.add_effect_with_name('blur', this._blurEffect); - this._blurEffect.color = bg; - } - - this._background.visible = true; - this._background.opacity = 200; - - let styles = []; - { - let ss = []; - - if (!this.blur_background) { - let clr = this._style.rgba(this.background_color); - ss.push(`\n background: rgba(${clr});`); - } - - if ( - this.border_thickness - // && !this.blur_background - ) { - let clr = this._style.rgba(this.border_color); - ss.push(`\n border: ${this.border_thickness}px solid rgba(${clr});`); - } - - styles.push(`#searchLight {${ss.join(' ')}}`); - styles.push(`#searchLightBlurredBackground {${ss.join(' ')}}`); - } - - // ss.push(`\n background-image: url("${bg}");`); - if ( - this.blur_background && - this.desktop_background_blurred && - this.monitor - ) { - let sw = this.monitor.width; - let sh = this.monitor.height; - let ss = []; - // ss.push(`\n background-image: url("${BLURRED_BG_PATH}");`); - ss.push( - `\n background-image: url("${this.desktop_background_blurred}");` - ); - ss.push(`\n background-size: ${sw}px ${sh}px;`); - ss.push(`\n background-position: top center;`); - // ss.push(`\n border: 2px solid red;`); - this._background.style = ss.join(' '); - - // styles.push(`#searchLightBlurredBackground {${ss.join(' ')}}`); - // styles.push(`#searchLight {${ss.join(' ')}}`); - } else { - this._background.style = ''; - } - - { - if (this.border_radius !== null) { - let rads = [0, 16, 18, 20, 22, 24, 28, 32]; - let r = rads[Math.floor(this.border_radius)]; - if (r) { - let st = `StBoxLayout.search-section-content { border-radius: ${r}px !important; }`; - st = '#searchLightBlurredBackgroundImage,\n' + st; // has no effect - st = '#searchLightBlurredBackground,\n' + st; // has no effect - st = '#searchLightBox,\n' + st; - st = '#searchLight,\n' + st; - styles.push(st); - } - } - } - - if (this.font_size !== null) { - let f = this.font_size_options[this.font_size]; - if (f) { - styles.push(`#searchLightBox * { font-size: ${f}pt !important; }`); - } - f = this.entry_font_size_options[this.entry_font_size]; - if (f) { - styles.push( - `#searchLightBox > StEntry, #searchLightBox > StEntry:focus { font-size: ${f}pt !important; }` - ); - } - } - - let clr = this._style.rgba(this.text_color); - if ((this.text_color || [1, 1, 1, 1])[3] > 0) { - styles.push(`#searchLightBox * { color: rgba(${clr}) !important }`); - } else { - styles.push('/* empty */'); - } - - // console.log(styles); - this._style.build('custom-search-light', styles); - } - - _toggle_search_light() { - if (this._inOverview) return; - if (!this._visible) { - this.show(); - if (this._entry) { - global.stage.set_key_focus(this._entry); - } - } else { - global.stage.set_key_focus(null); - } - } - - _add_events() { - global.stage.connectObject( - 'notify::key-focus', - this._onKeyFocusChanged.bind(this), - 'key-press-event', - this._onKeyPressed.bind(this), - this - ); - - global.display.connectObject( - 'notify::focus-window', - this._onFocusWindow.bind(this), - 'in-fullscreen-changed', - this._onFullScreen.bind(this), - this - ); - } - - _remove_events() { - global.display.disconnectObject(this); - global.stage.disconnectObject(this); - Main.overview.disconnectObject(this); - Main.sessionMode.disconnectObject(this); - Shell.AppSystem.get_default().disconnectObject(this); - } - - _onOverviewShowing() { - this._inOverview = true; - } - - _onOverviewHidden() { - this._inOverview = false; - } - - _onAppStateChanged(st) { - this._lastAppState = st; - if (this._visible) { - this.mainContainer.opacity = 0; - } - } - - _hidePopups() { - let popup = this._lastPopup; - this._lastPopup = null; - try { - if (!popup.close && popup._getTopMenu()) { - popup = popup._getTopMenu(); - } - - // elaborate way of hiding the popup - popup.opacity = 0; - this._startupSeq = this._hiTimer.runSequence([ - { - func: () => { - popup.opacity = 0; - }, - delay: 0, - }, - { - func: () => { - popup._delegate.close(false); - }, - delay: 250, - }, - ]); - } catch (err) { - console.log(err); - } - } - - _onFocusWindow(w, e) {} - - _onKeyFocusChanged(previous) { - if (!this._entry) return; - let focus = global.stage.get_key_focus(); - let appearFocused = - this._entry.contains(focus) || this._searchResults.contains(focus); - - if (!appearFocused) { - // popups are not handled well.. hide immediately - if ( - focus && - focus.style_class && - focus.style_class.includes('popup-menu') - ) { - this._lastPopup = focus; - this._hidePopups(); - } - - this.hide(); - } - - // hide window immediately when activated - if (focus.activate) { - if (!focus._activate) { - focus._activate = focus.activate; - focus.activate = () => { - this.mainContainer.opacity = 0; - focus._activate(); - }; - } - } - } - - _onKeyPressed(obj, evt) { - if (!this._entry) return; - let focus = global.stage.get_key_focus(); - if (!this._entry.contains(focus)) { - if (evt.get_key_symbol() === Clutter.KEY_Escape) { - this.hide(); - return Clutter.EVENT_STOP; - } - this._search._text.get_parent().grab_key_focus(); - } - return Clutter.EVENT_STOP; - } - - _onFullScreen() { - this.hide(); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/keybinding.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/keybinding.js deleted file mode 100755 index b0ebdda2..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/keybinding.js +++ /dev/null @@ -1,64 +0,0 @@ -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import Meta from 'gi://Meta'; -import Shell from 'gi://Shell'; - -// from https://stackoverflow.com/questions/12325405/gnome-shell-extension-key-binding - -export const KeyboardShortcuts = class { - constructor() {} - - enable() { - this._grabbers = {}; - this._eventId = global.display.connect( - 'accelerator-activated', - (display, action, deviceId, timestamp) => { - this._onAccelerator(action); - } - ); - } - - disable() { - this.unlisten(); - global.display.disconnect(this._eventId); - } - - listenFor(accelerator, callback) { - let action = global.display.grab_accelerator(accelerator, 0); - if (action == Meta.KeyBindingAction.NONE) { - console.log(`Unable to grab accelerator ${accelerator}`); - return; - } - - let name = Meta.external_binding_name_for_action(action); - Main.wm.allowKeybinding(name, Shell.ActionMode.ALL); - - this._grabbers[action] = { - name: name, - accelerator: accelerator, - callback: callback, - }; - - console.log(`Grabbed ${accelerator}`); - } - - unlisten() { - if (this._grabbers) { - Object.keys(this._grabbers).forEach((k) => { - Main.wm.removeKeybinding(this._grabbers[k].name, Shell.ActionMode.ALL); - // what the post in stackoverflow doesn't show is proper clean.. ungrab! - global.display.ungrab_accelerator(k); - }); - } - this._grabbers = {}; - } - - _onAccelerator(action) { - let grabber = this._grabbers[action]; - - if (grabber) { - grabber.callback(); - } else { - console.log(`No listeners ${action}`); - } - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/metadata.json deleted file mode 100755 index 79e5ff40..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/metadata.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Take the apps search out of overview.", - "gettext-domain": "search-light", - "name": "Search Light", - "schema-id": "org.gnome.shell.extensions.search-light", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/icedman/search-light", - "uuid": "search-light@icedman.github.com", - "version": 27 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/monitors.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/monitors.js deleted file mode 100755 index a6391232..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/monitors.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; - -// from Dash-to-Dock -export const MonitorsConfig = GObject.registerClass( - { - Signals: { - updated: {}, - }, - }, - class MonitorsConfig extends GObject.Object { - static get XML_INTERFACE() { - return '\ - \ - \ - \ - \ - \ - \ - \ - \ - \ - '; - } - - static get ProxyWrapper() { - return Gio.DBusProxy.makeProxyWrapper(MonitorsConfig.XML_INTERFACE); - } - - constructor() { - super(); - - this._monitorsConfigProxy = new MonitorsConfig.ProxyWrapper( - Gio.DBus.session, - 'org.gnome.Mutter.DisplayConfig', - '/org/gnome/Mutter/DisplayConfig' - ); - - // Connecting to a D-Bus signal - this._monitorsConfigProxy.connectSignal('MonitorsChanged', () => - this._updateResources() - ); - - this._primaryMonitor = null; - this._monitors = []; - this._logicalMonitors = []; - - this._updateResources(); - } - - _updateResources() { - this._monitorsConfigProxy.GetCurrentStateRemote((resources, err) => { - if (err) { - logError(err); - return; - } - - const [serial_, monitors, logicalMonitors] = resources; - let index = 0; - for (const monitor of monitors) { - const [monitorSpecs, modes_, props] = monitor; - const [connector, vendor, product, serial] = monitorSpecs; - this._monitors.push({ - index: index++, - active: false, - connector, - vendor, - product, - serial, - displayName: props['display-name'].unpack(), - }); - } - - for (const logicalMonitor of logicalMonitors) { - const [x_, y_, scale_, transform_, isPrimary, monitorsSpecs] = - logicalMonitor; - - // We only care about the first one really - for (const monitorSpecs of monitorsSpecs) { - const [connector, vendor, product, serial] = monitorSpecs; - const monitor = this._monitors.find( - (m) => - m.connector === connector && - m.vendor === vendor && - m.product === product && - m.serial === serial - ); - - if (monitor) { - monitor.active = true; - monitor.isPrimary = isPrimary; - if (monitor.isPrimary) this._primaryMonitor = monitor; - break; - } - } - } - - const activeMonitors = this._monitors.filter((m) => m.active); - if (activeMonitors.length > 1 && logicalMonitors.length === 1) { - // We're in cloning mode, so let's just activate the primary monitor - this._monitors.forEach((m) => (m.active = false)); - this._primaryMonitor.active = true; - } - - this.emit('updated'); - }); - } - - get primaryMonitor() { - return this._primaryMonitor; - } - - get monitors() { - return this._monitors; - } - } -); diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/preferences/keys.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/preferences/keys.js deleted file mode 100755 index d94b0a7e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/preferences/keys.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; - -import { PrefKeys } from './prefKeys.js'; - -export const schemaId = 'org.gnome.shell.extensions.search-light'; - -export const SettingsKeys = () => { - let settingsKeys = new PrefKeys(); - - settingsKeys.setKeys({ - 'border-radius': { - default_value: 0, - widget_type: 'scale', - }, - 'border-thickness': { - default_value: 0, - widget_type: 'dropdown', - test: { values: [0, 1, 2, 3] }, - }, - 'border-color': { - default_value: [1, 1, 1, 1], - widget_type: 'color', - }, - 'scale-width': { - default_value: 0.2, - widget_type: 'scale', - }, - 'scale-height': { - default_value: 0.2, - widget_type: 'scale', - }, - 'background-color': { - default_value: [0, 0, 0, 0.5], - widget_type: 'color', - }, - 'preferred-monitor': { - default_value: 0, - widget_type: 'dropdown', - test: { values: [0, 1, 2] }, - }, - 'msg-to-ext': { - default_value: '', - widget_type: 'string', - }, - 'secondary-shortcut-search': { - default_value: [], - widget_type: 'shortcut', - }, - 'shortcut-search': { - default_value: [], - widget_type: 'shortcut', - }, - 'popup-at-cursor-monitor': { - default_value: false, - widget_type: 'switch', - }, - 'blur-background': { - default_value: false, - widget_type: 'switch', - }, - 'blur-sigma': { - default_value: 30, - widget_type: 'scale', - }, - 'blur-brightness': { - default_value: 0.6, - widget_type: 'scale', - }, - 'font-size': { - default_value: 0, - widget_type: 'dropdown', - options: [0, 16, 18, 20, 22, 24], - }, - 'entry-font-size': { - default_value: 1, - widget_type: 'dropdown', - options: [0, 16, 18, 20, 22, 24], - }, - 'text-color': { - default_value: [1, 1, 1, 0], - widget_type: 'color', - }, - 'entry-text-color': { - default_value: [1, 1, 1, 0], - widget_type: 'color', - }, - 'show-panel-icon': { - default_value: false, - widget_type: 'switch', - }, - 'unit-converter': { - default_value: false, - widget_type: 'switch', - }, - 'currency-converter': { - default_value: false, - widget_type: 'switch', - }, - 'window-effect': { - default_value: 0, - widget_type: 'dropdown', - test: { values: [0, 1, 2] }, - themed: true, - }, - 'window-effect-color': { - default_value: [1, 1, 1, 1], - widget_type: 'color', - themed: true, - }, - }); - - return settingsKeys; -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/preferences/prefKeys.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/preferences/prefKeys.js deleted file mode 100755 index 6fbfc201..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/preferences/prefKeys.js +++ /dev/null @@ -1,285 +0,0 @@ -import Gdk from 'gi://Gdk'; -import GLib from 'gi://GLib'; - -export let PrefKeys = class { - constructor() { - this._keys = {}; - } - - setKeys(keys) { - Object.keys(keys).forEach((name) => { - let key = keys[name]; - this.setKey( - name, - key.default_value, - key.widget_type, - key.key_maps, - key.test, - key.callback, - key.options - ); - }); - } - - setKey(name, default_value, widget_type, maps, test, callback, options) { - this._keys[name] = { - name, - default_value, - widget_type, - value: default_value, - maps: maps, - test: test, - callback, - options, - object: null, - }; - } - - setValue(name, value) { - this._keys[name].value = value; - - let settings = this._settings; - let keys = this._keys; - if (settings) { - let key = keys[name]; - switch (key.widget_type) { - case 'switch': { - settings.set_boolean(name, value); - break; - } - case 'dropdown': { - settings.set_int(name, value); - break; - } - case 'scale': { - settings.set_double(name, value); - break; - } - case 'color': { - settings.set_value(name, new GLib.Variant('(dddd)', value)); - break; - } - case 'shortcut': { - settings.set_value(name, new GLib.Variant('as', value)); - break; - } - } - } - - if (this._keys[name].callback) { - this._keys[name].callback(this._keys[name].value); - } - } - - getKey(name) { - return this._keys[name]; - } - - getValue(name) { - let value = this._keys[name].value; - return value; - } - - reset(name) { - this.setValue(name, this._keys[name].default_value); - } - - resetAll() { - Object.keys(this._keys).forEach((k) => { - this.reset(k); - }); - } - - keys() { - return this._keys; - } - - connectSettings(settings, callback) { - this._settingsListeners = []; - - this._settings = settings; - let builder = this._builder; - let self = this; - let keys = this._keys; - - Object.keys(keys).forEach((name) => { - let key = keys[name]; - key.object = builder ? builder.get_object(key.name) : null; - switch (key.widget_type) { - case 'json_array': { - key.value = []; - try { - key.value = JSON.parse(settings.get_string(name)); - } catch (err) { - // fail silently - } - break; - } - case 'switch': { - key.value = settings.get_boolean(name); - if (key.object) key.object.set_active(key.value); - break; - } - case 'dropdown': { - key.value = settings.get_int(name); - try { - if (key.object) key.object.set_selected(key.value); - } catch (err) { - // - } - break; - } - case 'scale': { - key.value = settings.get_double(name); - if (key.object) key.object.set_value(key.value); - break; - } - case 'color': { - key.value = settings.get_value(name).deepUnpack(); - try { - if (key.object) { - key.object.set_rgba( - new Gdk.RGBA({ - red: key.value[0], - green: key.value[1], - blue: key.value[2], - alpha: key.value[3], - }) - ); - } - } catch (err) { - // - } - break; - } - case 'shortcut': { - key.value = settings.get_value(name).deepUnpack(); - break; - } - } - - this._settingsListeners.push( - settings.connect(`changed::${name}`, () => { - let key = keys[name]; - switch (key.widget_type) { - case 'json_array': { - key.value = []; - try { - key.value = JSON.parse(settings.get_string(name)); - } catch (err) { - // fail silently - } - break; - } - case 'switch': { - key.value = settings.get_boolean(name); - break; - } - case 'dropdown': { - key.value = settings.get_int(name); - break; - } - case 'scale': { - key.value = settings.get_double(name); - break; - } - case 'color': { - key.value = settings.get_value(name).deepUnpack(); - if (key.value.length != 4) { - key.value = [1, 1, 1, 0]; - } - break; - } - case 'string': { - key.value = settings.get_string(name); - break; - } - case 'shortcut': { - key.value = settings.get_value(name).deepUnpack(); - break; - } - } - if (callback) callback(name, key.value); - }) - ); - }); - } - - disconnectSettings() { - this._settingsListeners.forEach((id) => { - this._settings.disconnect(id); - }); - this._settingsListeners = []; - } - - connectBuilder(builder) { - this._builderListeners = []; - - this._builder = builder; - let self = this; - let keys = this._keys; - Object.keys(keys).forEach((name) => { - let key = keys[name]; - let signal_id = null; - key.object = builder.get_object(key.name); - if (!key.object) { - return; - } - - switch (key.widget_type) { - case 'json_array': { - // unimplemented - break; - } - case 'switch': { - key.object.set_active(key.default_value); - signal_id = key.object.connect('state-set', (w) => { - let value = w.get_active(); - self.setValue(name, value); - if (key.callback) { - key.callback(value); - } - }); - break; - } - case 'dropdown': { - signal_id = key.object.connect('notify::selected-item', (w) => { - let index = w.get_selected(); - let value = key.maps && index in key.maps ? key.maps[index] : index; - self.setValue(name, value); - }); - break; - } - case 'scale': { - signal_id = key.object.connect('value-changed', (w) => { - let value = w.get_value(); - self.setValue(name, value); - }); - break; - } - case 'color': { - signal_id = key.object.connect('color-set', (w) => { - let rgba = w.get_rgba(); - let value = [rgba.red, rgba.green, rgba.blue, rgba.alpha]; - self.setValue(name, value); - }); - break; - } - case 'button': { - signal_id = key.object.connect('clicked', (w) => { - if (key.callback) { - key.callback(); - } - }); - break; - } - } - - // when do we clean this up? - this._builderListeners.push({ - source: key.object, - signal_id: signal_id, - }); - }); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/prefs.js deleted file mode 100755 index dd7dfc47..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/prefs.js +++ /dev/null @@ -1,177 +0,0 @@ -// loosely based on JustPerfection & Blur-My-Shell - -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; - -import { ShortcutSettingWidget } from './shortcuts.js'; - -const GETTEXT_DOMAIN = 'search-light'; - -import { schemaId, SettingsKeys } from './preferences/keys.js'; -import { MonitorsConfig } from './monitors.js'; - -import { - ExtensionPreferences, - gettext as _, -} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class Preferences extends ExtensionPreferences { - constructor(metadata) { - super(metadata); - let iconTheme = Gtk.IconTheme.get_for_display(Gdk.Display.get_default()); - let UIFolderPath = `${this.path}/ui`; - iconTheme.add_search_path(`${UIFolderPath}/icons`); - // ExtensionUtils.initTranslations(GETTEXT_DOMAIN); - } - - find(n, name) { - if (n.get_name() == name) { - return n; - } - let c = n.get_first_child(); - while (c) { - let cn = this.find(c, name); - if (cn) { - return cn; - } - c = c.get_next_sibling(); - } - return null; - } - - dump(n, l) { - let s = ''; - for (let i = 0; i < l; i++) { - s += ' '; - } - print(`${s}${n.get_name()}`); - let c = n.get_first_child(); - while (c) { - this.dump(c, l + 1); - c = c.get_next_sibling(); - } - } - - addMenu(window, builder) { - // let menu_util = builder.get_object('menu_util'); - // window.add(menu_util); - - // let gwc = this.find(window, 'GtkWindowControls'); - // gwc.visible = false; - // console.log(gwc); - - let headerbar = this.find(window, 'AdwHeaderBar'); - if (!headerbar) { - return; - } - headerbar.pack_start(builder.get_object('info_menu')); - - // setup menu actions - const actionGroup = new Gio.SimpleActionGroup(); - window.insert_action_group('prefs', actionGroup); - - // a list of actions with their associated link - const actions = [ - { - name: 'open-bug-report', - link: 'https://github.com/icedman/search-light/issues', - }, - { - name: 'open-readme', - link: 'https://github.com/icedman/search-light', - }, - { - name: 'open-buy-coffee', - link: 'https://www.buymeacoffee.com/icedman', - }, - { - name: 'open-license', - link: 'https://github.com/icedman/search-light/blob/master/LICENSE', - }, - ]; - - actions.forEach((action) => { - let act = new Gio.SimpleAction({ name: action.name }); - act.connect('activate', (_) => - Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME) - ); - actionGroup.add_action(act); - }); - - // window.remove(menu_util); - } - - addButtonEvents(window, builder, settings) { - // - } - - fillPreferencesWindow(window) { - let builder = new Gtk.Builder(); - - let UIFolderPath = `${this.path}/ui`; - - builder.add_from_file(`${UIFolderPath}/general.ui`); - builder.add_from_file(`${UIFolderPath}/appearance.ui`); - builder.add_from_file(`${UIFolderPath}/accelerator.ui`); - builder.add_from_file(`${UIFolderPath}/menu.ui`); - window.add(builder.get_object('general')); - window.add(builder.get_object('appearance')); - window.set_search_enabled(true); - - // builder.get_object("providers-group").visible = false; - - let settings = this.getSettings(schemaId); - let settingsKeys = SettingsKeys(); - settingsKeys.connectBuilder(builder); - settingsKeys.connectSettings(settings); - - this.addButtonEvents(window, builder, settings); - this.addMenu(window, builder); - - this._monitorsConfig = new MonitorsConfig(); - this._monitorsConfig.connect('updated', () => this.updateMonitors()); - - // shortcuts widget - { - let placeholder = builder.get_object('shortcut-search-placeholder'); - placeholder.append( - new ShortcutSettingWidget( - builder.get_object('accelerator'), - settings, - 'shortcut-search', - window - ) - ); - } - - { - let placeholder = builder.get_object( - 'secondary-shortcut-search-placeholder' - ); - placeholder.append( - new ShortcutSettingWidget( - builder.get_object('accelerator'), - settings, - 'secondary-shortcut-search', - window - ) - ); - } - - this._builder = builder; - this.updateMonitors(); - } - - updateMonitors() { - let monitors = this._monitorsConfig.monitors; - let count = monitors.length; - let list = new Gtk.StringList(); - list.append('Primary Monitor'); - for (let i = 0; i < count; i++) { - let m = monitors[i]; - list.append(m.displayName); - } - this._builder.get_object('preferred-monitor').set_model(list); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/schemas/gschemas.compiled deleted file mode 100755 index 8ae5d3c6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/schemas/org.gnome.shell.extensions.search-light.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/schemas/org.gnome.shell.extensions.search-light.gschema.xml deleted file mode 100755 index 06e90e90..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/schemas/org.gnome.shell.extensions.search-light.gschema.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - - - 0 - Border radius - Set dash background border radius. - - - (1.,1.,1.,1.) - border color - Set border color. - - - 0 - Border thickness - Border thickness. - - - (0.,0.,0.,0.25) - Background color - Set window background color. - - - 0.1 - Scale width - Rescale width/ - - - 0.1 - Scale height - Rescale height/ - - - 0 - Preferred monitor to dock - Show dock on selected monitor. - - - 1 - Monitors Count - Monitors found by the extension. - - - - Shortcut - Keyboard shortcut for search - - - - Shortcut - Keyboard shortcut for search - - - false - Popup at Cursor - - - - "" - MsgBus - Preferences-Extension message bus - - - "" - MsgBus - Preferences-Extension message bus - - - false - Enable background blur - - - - 30 - Global sigma (gaussian blur radius) to use - - - 0.6 - Global brightness to use - - - 0 - Text size - - - 1 - Entry text size - - - (1.,1.,1.,0.) - text color - Set text color. - - - (1.,1.,1.,0.) - entry text color - Set entry text color. - - - false - Show panel icon - - - - false - Show unit converter - - - - false - Show currency converter - - - - 0 - Window effect - Set window rendering effect. - - - (1.,1.,1.,1.) - Rendering effect color - Set the window rendering effect color. - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/shortcuts.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/shortcuts.js deleted file mode 100755 index 629bd795..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/shortcuts.js +++ /dev/null @@ -1,174 +0,0 @@ -// https://github.com/eonpatapon/gnome-shell-extension-caffeine - -import Gdk from 'gi://Gdk'; -import Gtk from 'gi://Gtk'; -import GObject from 'gi://GObject'; - -const genParam = (type, name, ...dflt) => - GObject.ParamSpec[type]( - name, - name, - name, - GObject.ParamFlags.READWRITE, - ...dflt - ); - -const _ = (t) => t; - -export let ShortcutSettingWidget = class extends Gtk.Button { - static { - GObject.registerClass( - { - Properties: { - shortcut: genParam('string', 'shortcut', ''), - }, - Signals: { - changed: { param_types: [GObject.TYPE_STRING] }, - }, - }, - this - ); - } - - constructor(content, settings, key, window) { - super({ valign: Gtk.Align.CENTER, has_frame: false }); - this._key = key; - this._settings = settings; - this.window = window; - - this.content = content; - this.connect('clicked', this._onActivated.bind(this)); - - let label = new Gtk.ShortcutLabel({ disabled_text: _('New accelerator…') }); - this._label = label; - this.set_child(label); - - this.bind_property( - 'shortcut', - label, - 'accelerator', - GObject.BindingFlags.DEFAULT - ); - [this.shortcut] = this._settings.get_strv(this._key); - } - - _onActivated(widget) { - let ctl = new Gtk.EventControllerKey(); - - if (!this._editor) { - this._editor = new Gtk.Window({ - title: 'Accelerator', - modal: true, - hide_on_close: true, - transient_for: widget.get_root(), - width_request: 480, - height_request: 320, - child: this.content, - }); - } - - this._editor.add_controller(ctl); - ctl.connect('key-pressed', this._onKeyPressed.bind(this)); - this._editor.present(); - } - - _onKeyPressed(_widget, keyval, keycode, state) { - let mask = state & Gtk.accelerator_get_default_mod_mask(); - mask &= ~Gdk.ModifierType.LOCK_MASK; - - if (!mask && keyval === Gdk.KEY_Escape) { - this._editor.close(); - return Gdk.EVENT_STOP; - } - - if (keyval === Gdk.KEY_BackSpace) { - this.saveShortcut(); // Clear shortcut - return Gdk.EVENT_STOP; - } - - if ( - !this.isValidBinding(mask, keycode, keyval) || - !this.isValidAccel(mask, keyval) - ) { - return Gdk.EVENT_STOP; - } - - this.saveShortcut(keyval, keycode, mask); - return Gdk.EVENT_STOP; - } - - saveShortcut(keyval, keycode, mask) { - if (!keyval && !keycode) { - this.shortcut = ''; - } else { - this.shortcut = Gtk.accelerator_name_with_keycode( - null, - keyval, - keycode, - mask - ); - } - - console.log('saved new shortcut'); - - this.emit('changed', this.shortcut); - this._settings.set_strv(this._key, [this.shortcut]); - // this._editor.destroy(); - this._editor.close(); - } - - // Functions from https://gitlab.gnome.org/GNOME/gnome-control-center/-/blob/main/panels/keyboard/keyboard-shortcuts.c - - keyvalIsForbidden(keyval) { - return [ - // Navigation keys - Gdk.KEY_Home, - Gdk.KEY_Left, - Gdk.KEY_Up, - Gdk.KEY_Right, - Gdk.KEY_Down, - Gdk.KEY_Page_Up, - Gdk.KEY_Page_Down, - Gdk.KEY_End, - Gdk.KEY_Tab, - - // Return - Gdk.KEY_KP_Enter, - Gdk.KEY_Return, - - Gdk.KEY_Mode_switch, - ].includes(keyval); - } - - isValidBinding(mask, keycode, keyval) { - return !( - mask === 0 || - (mask === Gdk.SHIFT_MASK && - keycode !== 0 && - ((keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) || - (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) || - (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) || - (keyval >= Gdk.KEY_kana_fullstop && - keyval <= Gdk.KEY_semivoicedsound) || - (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) || - (keyval >= Gdk.KEY_Serbian_dje && - keyval <= Gdk.KEY_Cyrillic_HARDSIGN) || - (keyval >= Gdk.KEY_Greek_ALPHAaccent && - keyval <= Gdk.KEY_Greek_omega) || - (keyval >= Gdk.KEY_hebrew_doublelowline && - keyval <= Gdk.KEY_hebrew_taf) || - (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) || - (keyval >= Gdk.KEY_Hangul_Kiyeog && - keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) || - (keyval === Gdk.KEY_space && mask === 0) || - this.keyvalIsForbidden(keyval))) - ); - } - - isValidAccel(mask, keyval) { - return ( - Gtk.accelerator_valid(keyval, mask) || - (keyval === Gdk.KEY_Tab && mask !== 0) - ); - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/style.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/style.js deleted file mode 100755 index 2308307f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/style.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -import Gio from 'gi://Gio'; -import St from 'gi://St'; -const CustomStylesPath = '/tmp'; - -export let Style = class { - constructor() { - this.styles = {}; - this.style_contents = {}; - } - - unloadAll() { - let ctx = St.ThemeContext.get_for_stage(global.stage); - let theme = ctx.get_theme(); - Object.keys(this.styles).forEach((k) => { - let fn = this.styles[k]; - theme.unload_stylesheet(fn); - }); - } - - build(name, style_array) { - let fn = this.styles[name]; - let ctx = St.ThemeContext.get_for_stage(global.stage); - let theme = ctx.get_theme(); - - let content = ''; - style_array.forEach((k) => { - content = `${content}\n${k}`; - }); - - if (this.style_contents[name] === content) { - // console.log('skip regeneration'); - return; - } - - if (fn) { - theme.unload_stylesheet(fn); - } else { - fn = Gio.File.new_for_path(`${CustomStylesPath}/${name}.css`); - this.styles[name] = fn; - } - - this.style_contents[name] = content; - const [, etag] = fn.replace_contents( - content, - null, - false, - Gio.FileCreateFlags.REPLACE_DESTINATION, - null - ); - - theme.load_stylesheet(fn); - - // console.log(content); - } - - rgba(color) { - let clr = color || [1, 1, 1, 1]; - let res = clr.map((r) => Math.floor(255 * r)); - res[3] = clr[3].toFixed(1); - return res.join(','); - } - - hex(color) { - let r = Math.floor(color[0] * 255).toString(16); - let g = Math.floor(color[1] * 255).toString(16); - let b = Math.floor(color[2] * 255).toString(16); - if (r.length == 1) r += r; - if (g.length == 1) g += g; - if (b.length == 1) b += b; - let res = `#${r}${g}${b}`; - console.log(`${color} ${res}`); - return res; - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/stylesheet.css deleted file mode 100755 index 407b2478..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/stylesheet.css +++ /dev/null @@ -1,73 +0,0 @@ -#searchLight { - /* border: 2px solid red; */ -} - -#searchLight .overview-tile, -#searchLight .search-provider-icon, -#searchLight .list-search-provider-content, -#searchLight .list-search-result { - background-color: transparent; -} -#searchLight .overview-tile:hover, -#searchLight .overview-tile:active, -#searchLight .overview-tile:focus, -#searchLight .search-provider-icon:hover, -#searchLight .list-search-provider-content:hover, -#searchLight .list-search-result:hover, -#searchLight .search-provider-icon:active, -#searchLight .list-search-provider-content:active, -#searchLight .list-search-result:active, -#searchLight .search-provider-icon:focus, -#searchLight .list-search-provider-content:focus, -#searchLight .list-search-result:focus { - background-color: rgba(0,0,0,0.4); -} - -#searchLight .search-section-content { - background-color: rgba(0,0,0,0.2) !important; -} - -#searchLightBox { - /*padding: 14px;*/ - border: 0px; - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); -} - -#searchLightBox * { - color: white; -} - -#searchLightBox.light * { - color: black; -} - -#searchLightBox > StEntry:focus, -#searchLightBox > StEntry { - padding: 18px!important; - margin-top: 0px !important; - margin-bottom: 20px !important; - border-radius: 8px; - border: 0px !important; - border-width: 0px !important; - background: rgba(0,0,0,0); - /*font-size: 14pt !important;*/ -} - -#searchLightBox .app-well-app { - /*border: 2px solid red;*/ -} - -#searchLightBox.light StBoxLayout.search-section-content *:focus, -#searchLightBox.light StBoxLayout.search-section-content { - background: rgba(50,50,50,0.10) !important; -} - -#searchLightBox StBoxLayout.search-section-content *:focus, -#searchLightBox StBoxLayout.search-section-content { - background: rgba(100,100,100,0.20) !important; -} - -#searchLight #searchResultsContent { - padding-left: 12px; - padding-right: 12px; -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/timer.js b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/timer.js deleted file mode 100755 index 6a5923df..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/timer.js +++ /dev/null @@ -1,406 +0,0 @@ -'use strict'; - -import GLib from 'gi://GLib'; - -export const Timer = class { - constructor(name) { - this._name = name; - this._subscribers = []; - this._subscriberId = 0xff; - } - - initialize(resolution) { - this._resolution = resolution || 1000; - this._autoStart = true; - this._autoHibernate = true; - - this._hibernating = false; - this._hibernatCounter = 0; - this._hibernateWait = 250 + this._resolution * 2; - } - - shutdown() { - this._autoStart = false; - this._hibernating = false; - this.stop(); - } - - start(resolution) { - if (this.is_running()) { - // print('already running'); - return; - } - this._resolution = resolution || 1000; - this._time = 0; - this._timeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - this._resolution, - this.onUpdate.bind(this) - ); - this._hibernating = false; - this.onStart(); - } - - stop() { - if (!this.is_running()) { - // print('already stopped'); - return; - } - GLib.source_remove(this._timeoutId); - this._timeoutId = null; - this.onStop(); - } - - restart(resolution) { - this.stop(); - this.start(resolution || this._resolution || 1000); - } - - pause() { - if (!this.is_running()) { - return; - } - this._paused = true; - this.onPause(); - } - - resume() { - if (!this.is_running()) { - return; - } - this._paused = false; - this.onResume(); - } - - hibernate() { - if (!this.is_running()) { - return; - } - - this.stop(); - this._hibernating = true; - this._hibernatCounter = 0; - } - - is_running() { - return this._timeoutId != null; - } - - toggle_pause() { - if (!this.is_running()) { - return; - } - if (!this._paused) { - this.pause(); - } else { - this.resume(); - } - } - - onStart() { - // print(`started ${this._name} [${this.subscriberNames().join(',')}]`); - this._subscribers.forEach((s) => { - if (s.onStart) { - s.onStart(s); - } - }); - } - - onStop() { - this._subscribers.forEach((s) => { - if (s.onStop) { - s.onStop(s); - } - }); - // print(`stopped ${this._name}`); - } - - onPause() { - this._subscribers.forEach((s) => { - if (s.onPause) { - s.onPause(s); - } - }); - } - - onResume() { - this._subscribers.forEach((s) => { - if (s.onResume) { - s.onResume(s); - } - }); - } - - onUpdate() { - if (!this._timeoutId || this._paused) { - return true; - } - - this._subscribers.forEach((s) => { - if (s.onUpdate) { - s.onUpdate(s, this._resolution); - } - }); - - this._time += this._resolution; - - if (this._autoHibernate) { - if (!this._subscribers.length) { - this._hibernatCounter += this._resolution; - if (this._hibernatCounter >= this._hibernateWait) { - this.hibernate(); - } - } else { - this._hibernatCounter = 0; - } - } - - // print(`${this._time/1000} subs:${this._subscribers.length}`); - return true; - } - - runningTime() { - return this._time; - } - - subscribe(obj) { - if (!obj._id) { - obj._id = this._subscriberId++; - } - let idx = this._subscribers.findIndex((s) => s._id == obj._id); - if (idx == -1) { - this._subscribers.push(obj); - } else { - this._subscribers[idx] = { - ...this._subscribers[idx], - ...obj, - }; - obj = this._subscribers[idx]; - } - - if ( - (this._hibernating || this._autoStart) && - this._subscribers.length == 1 - ) { - this.start(this._resolution); - } - - // console.log(`subscribers: ${this.subscriberNames().join(',')}`); - return obj; - } - - unsubscribe(obj) { - let idx = this._subscribers.findIndex((s) => s._id == obj._id); - if (idx != -1) { - if (this._subscribers.length == 1) { - this._subscribers = []; - } else { - this._subscribers = [ - ...this._subscribers.slice(0, idx), - ...this._subscribers.slice(idx + 1), - ]; - } - } - } - - subscriberNames() { - return this._subscribers.map((s) => { - if (s._name) { - return s._name; - } - return `${s._id}`; - }); - } - - dumpSubscribers() { - if (this._name) { - print('--------'); - print(this._name); - } - this._subscribers.forEach((s) => { - print('--------'); - Object.keys(s).forEach((k) => { - print(`${k}: ${s[k]}`); - }); - }); - } - - runLoop(func, delay, name) { - if (typeof func === 'object') { - func._time = 0; - return this.subscribe(func); - } - let obj = { - _name: name, - _type: 'loop', - _time: 0, - _delay: delay, - _func: func, - onUpdate: (s, dt) => { - s._time += dt; - if (s._time >= s._delay) { - s._func(s); - s._time -= s._delay; - } - }, - }; - return this.subscribe(obj); - } - - runUntil(func, delay, name) { - if (typeof func === 'object') { - func._time = 0; - return this.subscribe(func); - } - let obj = { - _name: name, - _type: 'until', - _time: 0, - _delay: delay, - _func: func, - onUpdate: (s, dt) => { - s._time += dt; - if (s._time >= s._delay) { - if (s._func(s)) { - this.unsubscribe(s); - } - s._time -= s._delay; - } - }, - }; - return this.subscribe(obj); - } - - runOnce(func, delay, name) { - if (typeof func === 'object') { - func._time = 0; - return this.subscribe(func); - } - let obj = { - _name: name, - _type: 'once', - _time: 0, - _delay: delay, - _func: func, - onUpdate: (s, dt) => { - s._time += dt; - if (s._time >= s._delay) { - s._func(s); - this.unsubscribe(s); - } - }, - }; - return this.subscribe(obj); - } - - runDebounced(func, delay, name) { - if (typeof func === 'object') { - func._time = 0; - return this.subscribe(func); - } - let obj = { - _name: name, - _type: 'debounced', - _time: 0, - _delay: delay, - _func: func, - onUpdate: (s, dt) => { - s._time += dt; - if (s._time >= s._delay) { - s._func(s); - this.unsubscribe(s); - } - }, - }; - return this.subscribe(obj); - } - - runSequence(array, settings) { - if (typeof array === 'object' && !array.length) { - array._time = 0; - array._currentIdx = 0; - return this.subscribe(array); - } - let obj = { - _time: 0, - _currentIdx: 0, - _sequences: [...array], - ...settings, - onUpdate: (s, dt) => { - let current = s._sequences[s._currentIdx]; - if (!current) { - this.unsubscribe(s); - return; - } - s._time += dt; - if (s._time >= current.delay) { - current.func(current); - s._time = -current.delay; - s._currentIdx++; - if (s._currentIdx >= s._sequences.length && s._loop) { - s._currentIdx = 0; - } - } - }, - }; - return this.subscribe(obj); - } - - runAnimation(array, settings) { - if (typeof func === 'object' && !array.length) { - func._time = 0; - return this.subscribe(func); - } - - let duration = 0; - array.forEach((f) => { - if (!f._start) { - f._start = duration; - } - duration += f._duration; - }); - - let obj = { - _time: 0, - _duration: duration, - _loop: false, - _frames: [...array], - ...(settings || {}), - onUpdate: (s, dt) => { - s._time += dt; - - let frames = []; - if (s._frames) { - frames = s._frames.filter((f) => { - return f._start <= s._time && s._time < f._start + f._duration; - }); - } - s._currentFrames = frames; - - if (!s._func) { - s._func = (s) => { - s._currentFrames.forEach((f) => { - f._time = s._time - f._start; - f._func(f, s); - }); - }; - } - - if (s._time > s._duration) { - this.unsubscribe(s); - s._time = s._duration; - s._func(s); - return; - } - s._func(s); - }, - }; - return this.subscribe(obj); - } - - cancel(obj) { - if (obj) { - this.unsubscribe(obj); - } - } -}; diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/accelerator.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/accelerator.ui deleted file mode 100755 index 2e9356dc..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/accelerator.ui +++ /dev/null @@ -1,8 +0,0 @@ - - - - accelerator - Press shortcut keys... - preferences-desktop-keyboard-shortcuts-symbolic - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/appearance.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/appearance.ui deleted file mode 100755 index 515dd180..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/appearance.ui +++ /dev/null @@ -1,332 +0,0 @@ - - - - appearance - Appearance - overview-symbolic - - - Text - - - - Text Color - Select text color. Make value completely transparent to auto-adapt to background color. - text-color - - - center - false - 70px - 45px - true - true - - - - - - - false - Entry Text Color - Select entry text color. - entry-text-color - - - center - false - 70px - 45px - true - true - - - - - - - Text Size - Set font size of search text and search result items. - font-size - - - center - font-size-model - - - - - - - Search Text Size - Set font size for search input text. - entry-font-size - - - center - entry-font-size-model - - - - - - - - - Appearance - - - - Width - Set window width rescale. - scale-width - - - center - true - 140px - true - right - horizontal - 2 - scale-width-adjust - - - - - - - Height - Set window height rescale. - scale-height - - - center - true - 140px - true - right - horizontal - 2 - scale-height-adjust - - - - - - - Border Thickness - Set border thickness. - border-thickness - - - center - border-thickness-model - - - - - - - Border Radius - Set window border radius. - border-radius - - - center - true - 140px - false - right - horizontal - 0 - border-radius-adjust - - - - - - - Border Color - Select border color. - border-color - - - center - false - 70px - 45px - true - true - - - - - - - Window Effect - Set window rendering effect. - window-effect - - - center - window-effect-model - - - - - - - Window Effect Color - Select window effect color. - window-effect-color - - - center - false - 70px - 45px - true - true - - - - - - - - - Background - - - - Background Color - Set search window background color. - background-color - - - center - false - 70px - 45px - true - true - - - - - - - Background Blur - Add background blur with current wallpaper. Requires imagemagick installed. - blur-background - - - center - - - - - - - false - Sigma - The intensity of the blur. - blur-sigma - - - center - true - 200px - true - right - horizontal - 0 - blur-sigma-adjust - - - - - - - false - Brightness - The brightness of the blur effect, a high value might make the text harder to read. - blur-brightness - - - center - true - 200px - true - right - horizontal - 2 - blur-brightness-adjust - - - - - - - - - 0 - 7 - 1 - - - 0.0 - 1.0 - 0.01 - - - 0.0 - 1.0 - 0.01 - - - - None - 1px - 2px - - - - - Default - 16pt - 18pt - 20pt - 22pt - - - - - Default - 16pt - 18pt - 20pt - 22pt - 24pt - - - - 0 - 200 - 1 - - - 0.0 - 1.0 - 0.01 - - - - None - Tint - Monochrome - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/general.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/general.ui deleted file mode 100755 index be288258..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/general.ui +++ /dev/null @@ -1,133 +0,0 @@ - - - - general - General - general-symbolic - - - Keybindings - - - - Search - Set keyboard shortcut to popup Search box. Backspace to clear. - - - - 6 - 6 - 6 - 6 - - - - - - - Secondary Accelerator - Set another shortcut. Backspace to clear. - - - - 6 - 6 - 6 - 6 - - - - - - - - - Multi-Monitor - - - - Preferred Monitor - Show search box on selected monitor. - preferred-monitor - - - center - preferred-monitor-model - - - - - - - Popup at Cursor Monitor - Show search box at the monitor where cursor is located. - popup-at-cursor-monitor - - - center - - - - - - - - - Providers - - - - Currency Conversion - Enable currency conversion provider. - currency-converter - - - center - - - - - - - Unit Conversion - Enable unit conversion provider. - unit-converter - - - center - - - - - - - - - - - - - Icon - Show search icon panel box. - show-panel-icon - - - center - - - - - - - - - - Primary Monitor - Secondary Monitor - Monitor 3 - Monitor 4 - Monitor 5 - Monitor 6 - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/add-window-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/add-window-symbolic.svg deleted file mode 100755 index bdab3095..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/add-window-symbolic.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/applications-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/applications-symbolic.svg deleted file mode 100755 index 87f307f5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/applications-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg deleted file mode 100755 index 2eda98b7..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/bottom-panel-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/dash-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/dash-symbolic.svg deleted file mode 100755 index 5a78b467..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/dash-symbolic.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/general-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/general-symbolic.svg deleted file mode 100755 index e11da07f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/general-symbolic.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/heart-filled-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/heart-filled-symbolic.svg deleted file mode 100755 index 8378c9cb..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/heart-filled-symbolic.svg +++ /dev/null @@ -1,40 +0,0 @@ - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/other-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/other-symbolic.svg deleted file mode 100755 index 45e703e4..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/other-symbolic.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/overview-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/overview-symbolic.svg deleted file mode 100755 index 445f6621..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/overview-symbolic.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/remove-window-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/remove-window-symbolic.svg deleted file mode 100755 index a8da14f5..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/remove-window-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/reset-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/reset-symbolic.svg deleted file mode 100755 index e443de4f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/reset-symbolic.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/select-mode-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/select-mode-symbolic.svg deleted file mode 100755 index cad2da87..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/select-mode-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/select-window-symbolic.svg b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/select-window-symbolic.svg deleted file mode 100755 index cad2da87..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/icons/hicolor/scalable/actions/select-window-symbolic.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/legacy/general.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/legacy/general.ui deleted file mode 100755 index 14ab0564..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/legacy/general.ui +++ /dev/null @@ -1,253 +0,0 @@ - - - - True - False - 12 - 12 - 12 - 12 - vertical - - - - - True - True - - - True - False - 12 - 12 - 12 - 12 - vertical - - - True - False - 32 - - - True - False - center - Background Color - 0 - 1 - - - - - - - - center - false - 70px - 45px - true - true - - - - - - - start - center - Set search window background color. - - - - - - - - - True - True - - - True - False - 12 - 12 - 12 - 12 - vertical - - - True - False - 32 - - - True - False - center - Border Radius - 0 - 1 - - - - - - - - center - true - 140px - false - right - horizontal - 0 - border-radius-adjust - - - - - - - start - center - Set window background border radius. - - - - - - - - - True - True - - - True - False - 12 - 12 - 12 - 12 - vertical - - - True - False - 32 - - - True - False - center - Width - 0 - 1 - - - - - - - - center - true - 140px - true - right - horizontal - 2 - scale-width-adjust - - - - - - - start - center - Set window width rescale. - - - - - - - - - True - True - - - True - False - 12 - 12 - 12 - 12 - vertical - - - True - False - 32 - - - True - False - center - Height - 0 - 1 - - - - - - - - center - true - 140px - true - right - horizontal - 2 - scale-height-adjust - - - - - - - start - center - Set window height rescale. - - - - - - - - - - - 0 - 6 - 1 - - - 0.0 - 1.0 - 0.01 - - - 0.0 - 1.0 - 0.01 - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/menu.ui b/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/menu.ui deleted file mode 100755 index 5f73ddaa..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/search-light@icedman.github.com/ui/menu.ui +++ /dev/null @@ -1,41 +0,0 @@ - - - -
- - Project page - prefs.open-readme - - - Buy me a coffee - prefs.open-buy-coffee - - - Report a Bug - prefs.open-bug-report - - - License - prefs.open-license - - -
-
- - info_menu_model - heart-filled-symbolic - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/COPYING b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/COPYING deleted file mode 100755 index e55e5b8a..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/NEWS b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/NEWS deleted file mode 100755 index 4217e92f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/NEWS +++ /dev/null @@ -1,1439 +0,0 @@ -46.0 -==== -* system-monitor: Fix net speed [Florian; !313] -* Misc. bug fixes and cleanups [Aral; !311] - -Contributors: - Aral Balkan, Florian Müllner - -Translators: - Anders Jonsson [sv], Piotr Drąg [pl], Balázs Úr [hu], Milo Casagrande [it], - Quentin PAGÈS [oc], Athmane MOKRAOUI [kab], Changwoo Ryu [ko], - Ask Hjorth Larsen [da] - -46.rc -===== -* Fix window previews in workspace indicator [Florian; !304] -* Fix menu ornament in workspace indicator [Florian; !305] -* Misc. bug fixes and cleanups [Florian; !306, !309] - -Contributors: - Florian Müllner - -Translators: - Danial Behzadi [fa], Ekaterine Papava [ka], Sabri Ünal [tr], Artur S0 [ru], - Yuri Chornoivan [uk], Vasil Pupkin [be], Asier Sarasua Garmendia [eu], - Yaron Shahrabani [he], Brage Fuglseth [nb], Nathan Follens [nl], - Aurimas Černius [lt], Matej Urbančič [sl], Boyuan Yang [zh_CN], - Kukuh Syafaat [id], Fran Dieguez [gl], Andi Chandler [en_GB], - Baurzhan Muftakhidinov [kk], Rūdolfs Mazurs [lv], Guillaume Bernard [fr], - Daniel Mustieles [es], Jiri Grönroos [fi] - -46.beta -======= -* apps-menu: Rename Applications to Apps [Allan; !299] -* Misc. bug fixes and cleanups [Florian; !296, !297, !300, !301, !302] - -Contributors: - Allan Day, Florian Müllner - -Translators: - Gabriel Brand [de], Daniel Rusek [cs], Fran Dieguez [gl], - Aefgh Threenine [th], Vasil Pupkin [be], Artur S0 [ru], Yosef Or Boczko [he], - Sabri Ünal [tr] - -46.alpha -======== -* workspace-indicator: Fix initial preview visibility [Florian; !280, !292] -* screenshot-window-sizer: Fix cycling between sizes backwards [Florian; !284] -* Add back overview in Classic session [Florian; !287] -* Allow running Classic session headless [Jonas; !289] -* window-list: Fix buttons not being clickable at the screen edge - [Florian; !291] -* Add system-monitor extension [Florian; !277] -* Fixed crash [Florian; !290] -* Misc. bug fixes and cleanups [Florian; !276, !275, !278, !281, !286, !288] - -Contributors: - Jonas Ådahl, Florian Müllner - -Translators: - Kristjan SCHMIDT [eo], Brage Fuglseth [nb] - -45.0 -==== - -Contributors: - Andre Klapper - -Translators: - Bruce Cowan [en_GB] - -45.rc -===== -* Misc. bug fixes and cleanups [Florian; !267, !224, !272] - -Contributors: - Florian Müllner - -Translators: - Sabri Ünal [tr], Florentina Musat [ro], A S Alam [pa] - -45.beta -======= -* Port extensions to ESM [Florian; !259, !266, !268, !269] -* Misc. bug fixes and cleanups [Florian; !260, !261, !262, !263, !264] - -Contributors: - Florian Müllner - -Translators: - Efstathios Iosifidis [el] - -45.alpha -======== -* window-list: Modernize default styling [Alexander; !253] -* Replace classic styling with built-in light style [Florian; !254] -* window-list: Add tooltip for long window titles [Arik; !251] -* light-style: New extension [Florian; !256] -* Misc. bug fixes and cleanups [Florian; !255, !257] - -Contributors: - Florian Müllner, Arik W, Alexander Weichart - -44.0 -==== -* Bump version - -44.rc -===== -* Bump version - -44.beta -======= -* Tweak menu alignment [robxnano; !246] - -Contributors: - Florian Müllner, robxnano - -Translators: - Vasil Pupkin [be] - -43.1 -==== -* Fixed crash [Florian; !243] -* Misc. bug fixes and cleanups [mowemcfc; !244] - -Contributors: - Florian Müllner, mowemcfc - -Translators: - Sabri Ünal [tr] - -43.0 -==== - -Contributors: - Florian Müllner - -Translators: - Pawan Chitrakar [ne], Zurab Kargareteli [ka], Aleksandr Melman [ru] - -43.rc -===== -* Misc. bug fixes and cleanups [Florian; !240] - -Contributors: - Florian Müllner - -43.beta -======= -* Misc. bug fixes and cleanups [Florian; !237, !238] - -Contributors: - Florian Müllner - -Translators: - Nart Tlisha [ab] - -43.alpha -======== - -Contributors: - Florian Müllner - -Translators: - Marco Ciampa [it] - -42.3 -==== -* screenshot-window-sizer: Fix reported sizes on wayland [Florian; !232] -* window-list: Improve touch support [Florian; !233] - -Contributors: - Florian Müllner - -42.2 -==== -* native-window-placement: Adjust to gnome-shell 42 changes [Florian; !229] -* window-list: Fix visibility on non-primary monitors [Jason; !230] - -Contributors: - Jason Lynch, Florian Müllner - -Translators: - Cheng-Chia Tseng [zh_TW] - -42.1 -==== -* Misc. bug fixes and cleanups [Florian; !223, !222, !225] - -Contributors: - Florian Müllner - -Translators: - Milo Casagrande [it], Rūdolfs Mazurs [lv], Nathan Follens [nl], - Ngọc Quân Trần [vi], Zurab Kargareteli [ka] - -42.0 -==== - -Translators: - Philipp Kiemle [de], Balázs Úr [hu], Марко Костић [sr], sicklylife [ja], - Baurzhan Muftakhidinov [kk] - -42.rc -===== -* Misc. bug fixes and cleanups [Florian; !215, !218] - -Contributors: - Florian Müllner - -Translators: - Marek Černocký [cs], Dušan Kazik [sk], Piotr Drąg [pl], Jiri Grönroos [fi], - Luna Jernberg [sv], Alan Mortensen [da], Charles Monzat [fr], - Changwoo Ryu [ko] - -42.beta -======= -* workspace-indicator: Fix cancelling editing with Esc [Florian; !208] -* window-list: Update window tracking to avoid missing icons [Florian; !207] -* Use libadwaita for preferences [Florian; !209, !213] -* Adapt to Clutter grab API changes [Florian; !212] -* Misc. bug fixes and cleanups [Jan, Florian; !210, !214] - -Contributors: - Jan Beich, Florian Müllner, Naala Nanba - -Translators: - Boyuan Yang [zh_CN], Matej Urbančič [sl], Naala Nanba [ab], - Alexander Shopov [bg], Emin Tufan Çetin [tr] - -42.alpha -======== -* native-window-placement: Fix distorted layout in app grid [Sebastian; !189] -* window-list: Fix on-screen keyboard [Florian; !199] -* Misc. bug fixes and cleanups [Neal; Just; !195, !197] - -Contributors: - Piotr Drąg, Neal Gompa, Sebastian Keller, Florian Müllner, Just Perfection - -Translators: - Goran Vidović [hr], Sveinn í Felli [is], Yuri Chornoivan [uk], - Fabio Tomat [fur], Quentin PAGÈS [oc], Hugo Carvalho [pt], - Yaron Shahrabani [he], Jordi Mas i Hernandez [ca], MohammadSaleh Kamyab [fa], - Fran Dieguez [gl], Daniel Mustieles [es], Aleksandr Melman [ru], - Aurimas Černius [lt], Asier Sarasua Garmendia [eu], Kukuh Syafaat [id], - Rafael Fontenelle [pt_BR] - -41.0 -==== -* Bump version - -41.rc.1 -======= -* Fix pre-generating stylesheets in tarball [Florian; !190] - -Contributors: - Florian Müllner - -41.rc -===== -* window-list: Adapt to overview-on-startup [Florian; !185] -* apps-menu: Use a custom 'toggle-menu' shortcut [Florian; !173] -* Misc. bug fixes and cleanups [Florian; !186] - -Contributors: - Florian Müllner - -41.beta -======= -* window-list: Extend reactive area of minimap to screen edges [Adam; !171] -* drive-menu: Improve detection of network mounts [Florian; !27, !176] -* Use distinct gettext domain for e.g.o uploads [Florian; #335] -* Misc. bug fixes and cleanups [Florian; !172, !174, !177, !167, !178, !180, - !181, !182, !183] - -Contributors: - Marco Trevisan (Treviño), Adam Goode, Florian Müllner - -Translators: - Hugo Carvalho [pt], Juliano de Souza Camargo [pt], Alexander Shopov [bg] - -40.1 -==== -* Disable welcome dialog in classic session [Florian; !169] -* windowsNavigator: Adjust to a late gnome-shell change [Florian; !170] - -Contributors: - Florian Müllner - -Translators: - Ngọc Quân Trần [vi], Anders Jonsson [sv], Carmen Bianca BAKKER [eo], - Pawan Chitrakar [ne], Quentin PAGÈS [oc] - -40.0 -==== - -Translators: - Jiri Grönroos [fi] - -40.rc -===== -* native-window-placement: Adjust to gnome-shell changes [Florian; !164] -* windows-navigator: Adjust to gnome-shell changes [Florian; !163] -* window-list, workspace-indicator: Only show previews for up to six workspaces - [Florian; !165] -* window-list, workspace-indicator: Improve workspace preview appearance - [Florian; !166] - -Contributors: - Florian Müllner - -Translators: - Fran Dieguez [gl] - -40.beta -======= -* Add tooltips to workspace thumbnails [Florian; !155] -* Drop arrows from top bar menus [Florian; !156] -* drive-menu: Mark mounts that can be unmounted as removable [Michael; !152] -* Remove horizontal-workspaces extension [Florian; !158] -* Adjust to shell overview changes [Florian; !159, !160] -* Fix crashes [Daniel; !157] -* Misc. bug fixes and cleanups [Florian; !154, !161] - -Contributors: - Michael Lawton, Florian Müllner, Daniel van Vugt - -Translators: - Аляксей [be], A S Alam [pa] - -40.alpha.1 -========== -* Don't depend on sassc when building from tarball [Florian; !150] -* Port extensions preferences to GTK4 [Florian; !148] -* Misc. bug fixes and cleanups [Florian, Jonas; !149, !151, !153] - -Contributors: - Jonas Dreßler, Florian Müllner - -40.alpha -======== -* window-list: Honor changes in skip-taskbar property [Sergio; !130] -* window-list, workspace-indicator: Adjust to 3.38 changes [Florian; !133] -* window-list, workspace-indicator: Improve previews in workspace thumbs - [Florian; #260, !142] -* auto-move: Improve behavior on multi-monitor setups [Florian; !135] -* windowNavigator: Adjust to 3.38 changes [Thun; #259] -* Misc. bug fixes and cleanups [Florian, Jonas Å, Jordan, Ray; !131, !136, - !137, !140, !141, !144, !146, !145] - -Contributors: - Sergio Costas, Florian Müllner, Jordan Petridis, Thun Pin, Ray Strode, - Jonas Ådahl - -Translators: - Fabio Tomat [fur], Jordi Mas [ca] - -3.38.1 -====== - -Contributors: - Yacine Bouklif, Florian Müllner - -Translators: - Yacine Bouklif [kab], Cheng-Chia Tseng [zh_TW], Stas Solovey [ru], - Yosef Or Boczko [he] - -3.38.0 -====== - -Translators: - Balázs Meskó [hu], Alan Mortensen [da], Juliano Camargo [pt], Tim Sabsch [de], - Milo Casagrande [it], Rūdolfs Mazurs [lv] - -3.37.92 -======= - -Translators: - Nathan Follens [nl], Zander Brown [en_GB], Aurimas Černius [lt], - Marek Černocký [cs], Changwoo Ryu [ko], Dušan Kazik [sk] - -3.37.91 -======= - -Contributors: - Florian Müllner - -Translators: - Fran Dieguez [gl], Akarshan Biswas [bn_IN], Kukuh Syafaat [id], - Piotr Drąg [pl], Rafael Fontenelle [pt_BR], Jiri Grönroos [fi], - Марко Костић [sr], Goran Vidović [hr] - -3.37.90 -======= -* Misc. bug fixes and cleanups [Florian, Piotr; !126, !128] - -Contributors: - Piotr Drąg, Florian Müllner - -Translators: - Fabio Tomat [fur], Efstathios Iosifidis [el], Anders Jonsson [sv], - Asier Sarasua Garmendia [eu], Alexandre Franke [fr] - -3.37.3 -====== -* window-list, native-window-placement: Adjust to shell changes [Florian; !124] - -Contributors: - Florian Müllner - -Translators: - Jordi Mas [ca], sicklylife [ja], Boyuan Yang [zh_CN], - Baurzhan Muftakhidinov [kk] - -3.37.2 -====== -* window-list, auto-move: Modernize preference dialogs [Florian; !121] -* Adjust to gnome-shell changes [Florian; !122] - -Contributors: - Florian Müllner - -Translators: - Cheng-Chia Tseng [zh_TW], Yuri Chornoivan [uk], Daniel Mustieles [es], - Emin Tufan Çetin [tr], Danial Behzadi [fa], Daniel Șerbănescu [ro], - Matej Urbančič [sl] - -3.37.1 -====== -* drive-menu: Emphasize eject buttons [Florian; #223] -* user-theme: Add preference dialog [Florian; !117] -* window-list: Fix inconsistent state in preference dialog [Milan; !119] -* workspace-indicator: Overhaul preference dialog [Florian; !120] -* user-theme: Support session mode styles [Florian; !118] -* Misc. bug fixes and cleanups [Florian, Xiaoguang; !113, !106, !114, !116] - -Contributors: - Milan Crha, Florian Müllner, Xiaoguang Wang - -Translators: - Daniel Korostil [uk], Yosef Or Boczko [he], Kristjan SCHMIDT [eo], - Dz Chen [zh_CN], Danial Behzadi [fa], Yuri Chornoivan [uk], - Anders Jonsson [sv], Daniel Mustieles [es] - -3.36.0 -====== - -Contributors: - Florian Müllner - -3.35.91 -======= - -Contributors: - Florian Müllner - -Translators: - Zander Brown [en_GB] - -3.35.90 -======= -* Adjust to gnome-shell changes [Florian; !100, !101, !102] -* Force single-line window titles in window list [Florian; #202] -* Misc. bug fixes and cleanup [Florian; !104, !105] - -Contributors: - Florian Müllner - -Translators: - sicklylife [ja], Umarzuki Bin Mochlis Moktar [ms] - -3.35.3 -====== - -Translators: - Fran Dieguez [gl] - -3.35.2 -====== -* Adjust to gnome-shell changes [Marco, Florian; !89, !95, !96] -* window-list, workspace-indicator: Exclude DESKTOP windows from previews - [Florian; !93] -* screenshot-window-sizer: Fix cycling through all valid sizes [Willy; !97] - -Contributors: - Marco Trevisan (Treviño), Florian Müllner, Willy Stadnick - -3.34.1 -====== -* Adjust to gnome-settings-daemon plugin removals [Xiaoguang; !94] - -Contributors: - Florian Müllner, Xiaoguang Wang - -Translators: - Nathan Follens [nl], Dušan Kazik [sk], Ask Hjorth Larsen [da], - Yi-Jyun Pan [zh_TW] - -3.34.0 -====== - -Translators: - Rafael Fontenelle [pt_BR], Efstathios Iosifidis [el], Milo Casagrande [it], - Sabri Ünal [tr] - -3.33.92 -======= - -Translators: - Марко Костић [sr], Tim Sabsch [de], Rūdolfs Mazurs [lv], Matej Urbančič [sl], - Balázs Úr [hu], Claude Paroz [fr], Fran Dieguez [gl], Changwoo Ryu [ko], - Ryuta Fujii [ja], Fabio Tomat [fur], Goran Vidović [hr] - -3.33.91 -======= -* Misc. bug fixes and cleanups [Florian; !88, !90, !91, !92] - -Contributors: - Florian Müllner - -Translators: - Asier Sarasua Garmendia [eu], Anders Jonsson [sv], Marek Černocký [cs], - Kukuh Syafaat [id], Jiri Grönroos [fi], Florentina Mușat [ro], - Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl], Jordi Mas [ca], - Danial Behzadi [fa] -3.33.90 -======= -* window-list: Support showing windows from all workspaces [Florian; #154] -* Misc. bug fixes and cleanups [Florian; !86, !87] - -Contributors: - Florian Müllner - -Translators: - Jor Teron [mjw] - -3.33.4 -====== -* Make GNOME Classic more classic: - - Disable GNOME 3 overview [Florian; !69] - - Add window picker button to window list [Florian; !73, !80] - - Style improvements and fixes [Jakub; #169, !82] - - Support horizontal workspace layout in window list [Florian; !70] - - Add draggable previews to window list workspace switcher [Florian; !74] - - Arrange workspaces horizontally [Florian; !72] -* workspace-indicator: Support horizontal workspace layout [Florian; !71] -* workspace-indicator: Add draggable previews [Florian; !77] -* Misc. bug fixes and cleanups [Florian; !75, !76, !79, !78, #168, !84] - -Contributors: - Florian Müllner, Jakub Steiner, Jor Teron - -Translators: - Jor Teron [mjw] - -3.33.3 -====== -* Misc. bug fixes [Florian, Marco; !67, !68] - -Contributors: - Florian Müllner, Marco Trevisan (Treviño) - -3.33.2 -====== -* Misc. bug fixes and cleanups [Florian; !66] - -Contributors: - Florian Müllner - -3.33.1 -====== -* Misc. bug fixes [Florian; !64] - -Contributors: - Florian Müllner - -3.32.1 -====== -* Fix windowsNavigator extension after ES6 port [Florian; #143] -* screenshot-window-sizer: Add phone screenshot sizes [Adrien; !65] -* Misc. bug fixes and cleanups [Fabian; !62] - -Contributors: - Florian Müllner, Adrien Plazas, Fabian P. Schmidt - -3.32.0 -====== - -Contributors: - Florian Müllner - -Translations: - Victor Ibragimov [tg], Kristjan SCHMIDT [eo], Mart Raudsepp [et] - -3.31.92 -======= -* Misc. bug fixes and cleanups [Florian; !57, !58, !59, !60] - -Contributors: - Florian Müllner - -3.31.91 -======= -* apps-menu: Remove outdated legacy-tray handling [Florian; !53] -* user-theme: Allow using XDG user data dir [Tomasz; !55] -* Misc. bug fixes and cleanups [Florian; !52, !54, !56] - -Contributors: - Tomasz Gąsior, Florian Müllner - -Translators: - Matej Urbančič [sl], Gun Chleoc [gd] - -3.31.90 -======= -* Misc. bug fixes and cleanups [Florian; !49, !50, !51] - -Contributors: - Florian Müllner - -Translators: - Ryuta Fujii [ja], Charles Monzat [fr], Pieter Schalk Schoeman [af] - -3.31.2 -====== -* Remove obsolete alternate-tab extension [Florian; #786496] -* Adjust to gnome-shell changes [Florian; #113] - -Contributors: - Florian Müllner - -3.30.1 -====== -* apps-menu: Fix height on HiDPI systems [Florian; #102] -* window-list: Only switch between windows on active workspace when scrolling - [Florian; #78] - -Contributors: - Florian Müllner - -3.30.0 -====== -* Bump version - -3.29.91 -======= -* Misc. bug fixes [Florian; #90] - -Contributors: - Florian Müllner - -3.29.90 -======= -* Misc. bug fixes [Florian; #786496] - -Contributors: - Florian Müllner - -3.29.3 -====== -* Adjust to global.screen removal [Jonas; #759538] - -Contributors: - Jonas Ådahl, Florian Müllner - -3.29.2 -====== -* Misc. bug fixes [Florian; #69] - -Contributors: - Florian Müllner - -3.28.1 -====== -* Misc. bug fixes [Xiaoguang, Florian; #59, #62] - -Contributors: - Florian Müllner, Xiaoguang Wang - -Translators: - Dz Chen [zh_CN] - -3.28.0 -====== - -Contributors: - Florian Müllner, Xiaoguang Wang - -Translators: - Aman Alam [pa], Bruce Cowan [en_GB] - -3.27.92 -======= - -Contributors: - Florian Müllner - -Translators: - Piotr Drąg [es], GNOME Translation Robot [gd], Daniel Șerbănescu [ro] - -3.27.91 -======= -* places-menu: Support unmounting ejectable places [Rémy; #17] -* apps-menu: Support separators and custom sort order [Florian; #27] -* Port to meson [Florian; #31, #45] -* window-list: Fix missing icons on wayland [Florian; #10] -* places-menu: Fix terminating gnome-shell with recent gjs [Florian; #44] -* auto-move: Make it work with wayland windows [Florian; #33] -* Classic theme fixes [Florian, Jonas; #26, #41, #39, #40] -* Require sassc for classic styling [Florian; !28] -* Misc. bug fixes [Piotr, Florian; #772211, #32, #30] - -Contributors: - Jeremy Bicha, Piotr Drąg, Jonas Kümmerlin, Rémy Lefevre, Iñigo Martínez, - Florian Müllner - -Translators: - Matej Urbančič [sl], Kjartan Maraas [nb] - -3.27.1 -====== -* updated translations (ca@valencia) - -3.26.1 -====== -* native-window-placement: Adjust to gnome-shell changes -* updated translations: el, fa, ru, sv - -3.26.0 -====== -* updated translations (be, bg, ca, da, eu, fi, is, it, ko, lv, ml, - nl, pt_BR, vi, zh_TW) - -3.25.91 -======= -* updated translations (ca, fr, it, pl, pt_BR, sr, sr@latin, tr) - -3.25.90 -======= -* updated translations (es, gl, hr, hu, kk, sl, sv, sv) - -3.25.4 -====== -* screenshot-window-sizer: Fix backward cycling -* updated translations (ar, be, ca, cs, de, fur, id, lt, pl, sk) - -3.25.3 -====== -* places-menu: Use mount operation if necessary -* window-list: Respect MWM hints -* updated translations (es, fur, kk) - -3.25.2 -====== -* places-menu: Make URI launching asynchronous -* updated translations (de, fur, hr, hu, id, sl) - -3.25.1 -====== -* apps-menu: Mark copied launchers as trusted -* places-menu: Make icon lookup asynchronous -* updated translations (hr) - -3.24.1 -====== -* apps-menu: Allow creating desktop launchers via DND -* updated translations (el, vi) - -3.24.0 -====== -* updated translations (lv, tr) - -3.23.92 -======= -* update classic theme -* updated translations (be, ko, ca, da, cs, ru, lt) - -3.23.91 -======= -* updated translations (de, es, eu, fi, fr, fur, gl, hu, id, it, kk, nb, pl, pt_BR, - sk, sr, sr@latin, sv, uk, zh_TW) - -3.23.90 -======= -* window-list: Improve styling -* window-list: Hide workspace indicator when there's a single (static) workspace -* new translation (be) - -3.23.2 -====== -* alternateTab: Don't take over 'switch-group' shortcut -* updated translations (zh_CN) - -3.22.1 -====== -* window-list: Update icon on app changes - -3.22.0 -====== -* updated translations (en_GB) - -3.21.92 -======= -* update style -* updated translations (pl, vi) - -3.21.91 -======= -* updated translations (pl) - -3.21.90 -======= -* updated translations (es, gu) - -3.21.4 -====== -* apps-menu: Fix entries from non-standard AppDir directories - -3.21.3 -====== -* adjust to gnome-shell changes -* updated translations (oc) - -3.21.2 -====== -* version bump, nothing to see here - -3.20.1 -====== -* update classic style -* updated translations (gd, oc) - -3.20.0 -====== -* version bump, nothing to see here - -3.19.92 -======= -* version bump, nothing to see here - -3.19.91 -======= -* updated translations (oc) - -3.19.90 -======= -* version bump, nothing to see here - -3.19.4 -====== -* screenshot-window-sizer: HiDPI support -* Fix gnome-shell component in classic session -* updated translations (lt) - -3.19.3 -====== -* native-window-placement: Don't let border overlap title -* apps-menu: Fix handling of .desktop files in subdirectories -* updated translations (is) - -3.19.2 -====== -* updated translations (gd) - -3.19.1 -====== -* Fix some theme issues - -3.18.1 -====== -* window-list: Fix accessibility of window buttons -* apps-menu: Fix unreliable highlight -* updated translations (ar) - -3.18.0 -====== -* Bump version - -3.17.92 -======= -* places: Include DESKTOP when desktop icons are enabled -* updated translations (fa) - -3.17.91 -======= -* updated translations (nl, pl, zh_TW) - -3.17.90 -======= -* window-list: Improve application ordering -* workspace-indicator: Use consistent workspace numbering - -3.17.4 -====== -* updated translations (fur) - -3.17.3 -====== -* window-list: Adjust with text-scaling-factor -* classic style updates -* updated translations (pt, ro) - -3.17.2 -====== -* updated translations (oc, pt, zh_CN) - -3.17.1 -====== -* style updates -* updated translations (oc) - -3.16.1 -====== -* window-list: Fix workspace indicators popup menu position -* apps-menu: Fix taking over panel-main-menu shortcut -* updated translations (et, ja, lv) - -3.16.0 -====== -* updated translations (ca) - -3.15.92 -======= -* classic: Update theme -* update for mutter API changes -* updated translations (bg, bs, da, fi, pa, ru, sr, sr@latin, tg) - -3.15.91 -======= -* classic: Update theme -* systemMonitor extension was removed, as the message tray where it - put its indicator no longer exists -* window-list: Adjust for gnome-shell changes -* updated translations (gl, it, kk, ko, lt, pl, sk, uk, zh_TW) - -3.15.90 -======= -* classic: Visual refresh based on new shell theme -* window-list: Adjust for gnome-shell changes -* updated translations (an, el, eo, eu, fr, he, is, sv, tr) - -3.15.4 -====== -* window-list: Improve interaction with system modal dialogs -* updated translations (cs, de, es, eu, fur, hu, id, nb, pt_BR, ru, sl, vi) - -3.15.3.1 -======== -* adjust to gnome-shell change - -3.15.3 -====== -* classic-mode: Add high-contrast theme variant, drop .desktop file -* places-menu: Fix error when XDG user directories are not set up -* window-list: Add option to show on all monitors -* updated translations (eu, hu, kk, ro, tr) - -3.15.2 -====== -* removable-drive, user-theme, window-list: Update for gnome-shell changes -* apps-menu: Fix some visual glitches -* Fix classic mode style -* updated translations (an, cs, he, vi) - -3.15.1 -====== - * updated translations (es, nb) - -3.14.1 -====== - * alternateTab: Fix dismissing popup with Escape - * some improvements to the window-list - (spacing in app buttons, no flash when closing windows with auto-grouping) - * updated translations (lv, it, pt, bg) - -3.14.0 -====== - * updated translations (bn_IN, hi, kn, sr, sr@latin, uk) - -3.13.92 -======= -* new extension: screenshot-window-sizer -* window-list: Don't add sticky windows more than once -* updated translations (da, de, fi, ko, mr, ms, ne, pa, pl, sk, sv, ta, te, tr) - -3.13.91 -======= -* window-list: restore fitts'ability of workspace button -* updated for gnome-shell changes -* updated translations (cs, kk, fr, or, fa, ja, gu, id) - -3.13.90 -======= -* updated translations (as, ca, eu, nl, zh_CN, zh_HK, zh_TW) - -3.13.4 -====== -* Updated for gnome-shell changes -* updated translations (el, gl, ru) - -3.13.3 -====== -* Tweak preference UIs some more -* Fix classic mode schema overrides -* updated translations (es, he, hu, lt, nb, pt_BR, sl, tr) - -3.13.2 -====== -* Fix sorting of grouped buttons in window list -* Tweak preference UIs -* updated translations (en_GB) - -3.13.1 -====== -* add DesktopNames key to the classic session file -* classic theme: remove rounded corners from tile previews -* window-list: don't shift message tray on other monitors -* auto-move-windows: several fixes and updates for api changes -* launch-new-instances: updates for api changes -* updated translations (ja, km) - -3.12.0 -====== -* updated translations (zh_HK, zh_TW) - -3.11.92 -======= -* nothing to see here, move on - -3.11.91 -======= -* updated translations (ko, fur) - -3.11.90 -======= -* several fixes and improvements to the window-list - (can be scrolled, works correctly with the OSD - keyboard, filters skip-taskbar windows, does not - force all notifications to bold) -* drive-menu fixed not to show shadowed mounts -* updates for gnome-shell changes (launch-new-instance, - auto-move-windows, places-menu) -* build system fixes for systems without /bin/bash -* updated translations (or, tr, uk) - -3.11.5 -====== -* updates for gnome-shell changes -* updated translations (kn) - -3.11.4 -====== -* classic mode now supports session saving -* updates for gnome-shell changes -* updated translations (ar, kn) - -3.11.3 -====== -* workspace-indicator is vertically aligned now -* updated translations (ar, eo, ta, te) - -3.11.2 -====== -* updated translations (zh_CN) - -3.11.1 -====== -* ignore shadowed mounts in drive-menu extension -* updates for gnome-shell/gjs changes -* updated translations (el, th) - -3.10.1 -====== -* updated translations (af, ca, ca@valencia, de, et, eu, fa, - hu, lt, lv, nb, nl, pa, pt, sk, sr, sr@latin, tr) - -3.10.0 -====== -* updated translations (as, cs, da, es, et, fi, fr, gl, - he, id, it, kk, lt, lv, pa, pl, pt, pt_BR, ru, sl, tg, - uk, zh_HK, zh_TW) - -3.9.92 -====== -* more updates and fixes for gnome-shell master changes - and regressions (systemMonitor, window-list, apps-menu) -* lots of updated translations (ar, as, cs, da, de, el, es, - eu, fi, gl, he, hu, it, ja, kk, ko, lv, nb, nl, pa, pl, - pt_BR, ru, sk, sr, sr@latin, ta, tg) - -3.9.91 -====== -* update the classic mode session and theme to work with the - new system menu -* the usual round of updates and fixes for gnome-shell - API changes -* updated translations (de, it, lt, nl, pl, pt_BR, sk, - zh_HK, zh_TW) - -3.9.90 -====== -* xrandr-indicator was removed, as the implementation - was incompatible with the new DisplayConfig mutter API -* various extensions were updated for the 3.9.90 gnome-shell API -* updated translations (cs, es, fur, gl, he, hu, id, ja, sl, tg, - zh_CN, zh_HK, zh_TW) - -3.9.5 -===== -* alternative-status-menu was removed entirely, as - it does not fit in the designs of the new unified - status menu -* updated translations (as, gu, it, ru) - -3.9.4 -===== -* apps-menu: fixed handling of hot corner in case - of screen reconfiguration -* alternative-status-menu now correctly honors polkit - for hibernation -* user-menu now loads themes from $XDG_DATA_HOME too -* translation updates (de, id, pt_BR, vi, zh_CN, ml) - -3.9.3 -===== -* classic mode mini extensions were replaced with a - GSettings override specified in the .json file -* styling of classic mode improved -* native-window-placement is back working on 3.9 -* misc bug fixes -* traslation updates (an, cs, el, es, gl, nb, pl, sk, tg) - -3.9.2 -===== -* apps-menu: appearance of the scrollbars was improved -* window-list is a little taller in classic mode (to account - for the workspace switcher) -* alternative-status-menu honors again the dconf configuration -* translation updates (sr) - -3.9.1 -===== -* updates to window-list, xrandr-indicator, - workspace-indicator, windowsNavigator for gnome-shell - changes -* translation updates (cs, es, lt, pl, pt_BR, sl) - -3.8.1 -===== -* many improvements to window-list: - - windows are activated by DND over them - - window buttons now have the right size, - even if the text is smaller or larger - than the ideal - - window buttons can be grouped automatically - when the panel becomes crowded - - added a workspace switcher menu -* added keyboard navigation to apps-menu -* small tweaks to classic-mode theme, in particular - for menus -* translation updates (gl, ko, sr) - -3.8.0 -===== -* translation updates (hu, ja, fi, it) - -3.7.92 -====== -* misc bug fixes to app-menu and window-list -* translation updates (de, sl, pt_BR, ru) - -3.7.91 -====== -* various updates for shell changes -* update window-list to always use application icons -* update apps-menu to not load subdirectories as - separate categories -* translation updates (lt, zh_CN) - -3.7.90 -====== -* various fixes to make places-menu behave more - like Nautilus, including showing the machine - name in place of File System -* various updates for shell changes -* alternative-status-menu no longer supports - ConsoleKit systems, you need to install logind - to have suspend or hibernate -* translation updates (es, cz, pl, sr) - -3.7.5.1 -======= -* new extension forgotten in previous NEWS entry: - windows-list -* also forgotten previously: classic mode got a new - GNOME2 style -* build fixes - -3.7.5 -===== -* places-menu is back in the classic extensions, with - a new old GNOME-2 look -* classic mode moved the date menu to right, where we - all know it rightly belongs -* apps-menu received a face-lift, with the inclusion - of a reduced form of AxeMenu -* new extension in the classic set: launch-new-instance, - which modifies the behavior of clicking in the dash - and app launcher -* alternate-tab, native-window-placement and windowsNavigator - updated for gnome-shell changes -* translation updates (es, cz, pl) - -3.7.4 -===== -* a separate configure switch has been added to enable - classic mode session definitions -* places-menu is no longer part of the classic-mode - extension set -* updated translations (ar, gl, hu, lt, pt_BR, sr) - -3.7.3 -===== -* new extensions: default-min-max, static-workspaces -* alternate-tab now uses the built-in window switcher and just - takes over the switch-application keybinding -* workspace-indicator: is no longer part of classic-mode -* we now install classic-mode data files for gdm, gnome-session - and gnome-shell, so if you enable classic-mode you get a new - session option in GDM -* updated translations (ar, es, pl, ru, sl, zh_HK, zh_TW) - -3.7.2 -===== -* fixed crashes with places-menu, windowsNavigator, alternate-tab - and native-window-placement -* alternate-tab now hides attached modal dialogs -* places-menu has restored support for Nautilus 3.4 -* the default for hibernate is now to show in alternative-status-menu -* some extensions are now tagged as "classic", and can be chosen with - --enable-extensions=classic-mode -* dock and gajim were removed at the beginning of the 3.7.1 cycle, - as they were buggy and unmaintained -* updated translations (ar, cs, de, el, es, gl, id, lt, lv, pa, pl - ru, sk, sl, sr, sr@latin) - -3.6.1 -===== -* fixed alternative-status-menu for the new lock screen -* squashed some alternate-tab warnings -* drive-menu now works with 3.6 again -* updated translations (ar, cs, el, es, gl, id, lv, pl, sl) - -3.6.0 -===== -* major rework in places menu, to make it work without - removed supporting code in the shell and to make it look like - the nautilus sidebar - (similar work would be needed for drive-menu, not done yet) -* updated translations (ca, cs, de, el, en_GB, es, fi, hu, id, lt, - pl, pt_BR, ru, sl, sr) - -3.5.91 -====== -* various crashers were fixed in alternative-tab -* auto-move-windows now can be made to work with static workspaces -* place-menu is now on the left and uses symbolic icons like Files -* StIconType usage was removed from all extensions, after it was - removed in core -* systemMonitor, xrandr-indicator, apps-menu, places-menu, - alternative-status-menu were updated for the newer shell -* updated translations (es, gl, it, pl, sl) - -3.5.90 -====== -* alternate-tab has been reworked again, the old mode switch - was removed and the all&thumbnails code extended to handle - icons and filtering to the workspace -* alternate-tab thumbnails now reflect the aspect ratio of the windows -* systemMonitor now shows a tooltip above the indicator -* native-window-placement, systemMonitor and windowsNavigator have been updated - for the newer shell -* updated translations (es, pa) - -3.5.5 -===== -* convenience module has been relicensed to BSD, - for compatibility with GPLv3 extensions -* alternate-tab has been refactored and seen various - improvements to all&thumbnails mode, including a new - overlaid application icon -* updated translations (lt, id, sr) - -3.5.4 -===== -* updated translations (de, es, ar, sl, lv, zh_CN) - -3.5.2 -===== -* removable-drive-menu is now a11y friendly -* the dock can now be placed on any monitor, not just the primary -* dock is now clipped to its monitor -* alternative-status-menu now exposes GSettings for Suspend - and Hibernate visibility - no UI yet -* more gnome-shell API changes (places-menu, removable-drive-menu, - alternative-status-menu) -* miscellaneous bug fixes (native-window-placement, gajim, - auto-move-windows) -* updated translations - -3.4.0 -===== -* build system improvements -* updated translations (ar, cs, fr) - -3.3.92 -====== -* various updates for gnome-shell API changes (dock, - native-window-placement) -* local-install is now a make rule, not a shell script -* updated translations (zh, es, sw, ga, hu, it, no, pt_BR, de, sl, - pl, la, fi, sr) - -3.3.90 -====== -* system wide installation via "make install" is possible - again -* alternate-tab can now pre-activate the selected window -* auto-move-windows, workspace-indicator and example gained - new preference dialogs -* workspace-indicator: fixed a bug wrt focus stealing prevention -* updated translations (es, pt_BR, it, sl, gl, sr) - -3.3.5 -===== -* improvements to the build system and convenience module, - making it easier for other extensions to use, and bringing - it up to date with gnome-shell changes -* all extensions were ported to the Lang.Class framework - (except xrandr-indicator, which is pending GDBus merge) -* alternate-tab and dock were slightly refactored to clean up - some old code - -3.3.4 -===== -* improved styling of windowsNavigator tooltips -* fixed windowsNavigator when used with the numeric keypad -* fixed native-window-placement with custom button layout -* updated translations (pt_BR, cz) - -3.3.3 -===== -* windowsNavigator was fixed to work with azerty keyboards -* drive-menu was changed to use media-eject icon instead of media-optical -* dock: the default value of hide-effect is now move -* dock: if autohide is disabled, now it pushes maximized windows aside -* dock was updated to match current core shell styling -* native-window-placement: position stategy setting was removed -* alternative-status-menu no longer conflicts with other extensions - in the user menu -* various other minor bug fixes -* updated translations (zh, uk, es, it, cz, sl, sk, fi) - -3.3.2 -===== -* all extensions are now self-contained, including l10n and settings -* introduce a convenience module that can be shared among all extensions -* you can know build an installable zip file with make zip-file -* apps-menu no longer shows NoDisplay apps -* alternative-status-menu, alternate-tab: fix for master shell - -3.2.1 -===== -* dock: added "move" hide effect -* systemMonitor: now it enables/disables properly -* systemMonitor: improved styling -* alternate-tab: both modes now work with gnome-shell 3.2 -* various other bug fixes -* updated translations - -3.2.0 -===== - -* various: update for gnome-shell API changes - -3.1.91 -====== - -* gajim: update for gnome-shell API changes - -3.1.90 -====== - -* All extensions have been ported to the new extension - system (including live enable/disable) -* Updated translations -* xrandr-indicator no longer requires a specific gjs version -* windowsNavigator fixed for more than 2 workspaces - -3.1.4 -===== - -* New extension: a menu for changing workspace (workspace-indicator) -* systemMonitor: lower the requirement on libgtop -* auto-move-windows: open overview when last window on - last workspace is closed -* dock: implement autohiding, with various configurable - effects -* alternate-tab: more configurable implementations available -* native-window-placement: don't rearrange the windows when - the workspace switcher is shown/hidden -* update for gnome-shell 3.1.4 API changes - -3.1.3 -===== - -* New extension: a menu for removable drives (drive-menu -* New extensions: GNOME 2 like menus for apps and places - (apps-menu, places-menu) -* New extension: additional configurability for the window - layout in the overview, including a mechanism similar to - KDE4 (native-window-placement) -* New extension: a message tray indicator for CPU and memory - usage (uses libgtop) (systemMonitor) -* user-theme: fixed resetting theme -* user-theme: support themes installed in /usr/share/themes -* alternative-status-menu: ported to gnome-shell master -* dock: ported to gnome-shell master -* dock: make position configurable (can be left or right) -* Updated translations - -3.0.2 -===== - -* Updated translations. -* Fixed bug #647386 (reverting of user-theme to default) -* Fixed bug #647599 (support globally installed themes) -* Added license and README diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/extension.js deleted file mode 100755 index fd7a7b43..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/extension.js +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-FileCopyrightText: 2011 John Stowers -// SPDX-FileCopyrightText: 2011 Giovanni Campagna -// SPDX-FileCopyrightText: 2011 Elad Alfassa -// SPDX-FileCopyrightText: 2014 Florian Müllner -// -// SPDX-License-Identifier: GPL-2.0-or-later - -// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- -// Load shell theme from ~/.local/share/themes/name/gnome-shell - -import Gio from 'gi://Gio'; - -import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; - -import {getThemeDirs, getModeThemeDirs} from './util.js'; - -const SETTINGS_KEY = 'name'; - -export default class ThemeManager extends Extension { - enable() { - this._settings = this.getSettings(); - this._settings.connectObject(`changed::${SETTINGS_KEY}`, - this._changeTheme.bind(this), this); - this._changeTheme(); - } - - disable() { - this._settings?.disconnectObject(); - this._settings = null; - - Main.setThemeStylesheet(null); - Main.loadTheme(); - } - - _changeTheme() { - let stylesheet = null; - let themeName = this._settings.get_string(SETTINGS_KEY); - - if (themeName) { - const stylesheetPaths = getThemeDirs() - .map(dir => `${dir}/${themeName}/gnome-shell/gnome-shell.css`); - - stylesheetPaths.push(...getModeThemeDirs() - .map(dir => `${dir}/${themeName}.css`)); - - stylesheet = stylesheetPaths.find(path => { - let file = Gio.file_new_for_path(path); - return file.query_exists(null); - }); - } - - if (stylesheet) - log(`loading user theme: ${stylesheet}`); - else - log('loading default theme (Adwaita)'); - Main.setThemeStylesheet(stylesheet); - Main.loadTheme(); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/metadata.json deleted file mode 100755 index a2dffe8f..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/metadata.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Load shell themes from user directory.", - "extension-id": "user-theme", - "gettext-domain": "gnome-shell-extension-user-theme", - "name": "User Themes", - "original-authors": [ - "john.stowers@gmail.com" - ], - "settings-schema": "org.gnome.shell.extensions.user-theme", - "shell-version": [ - "46" - ], - "url": "https://gitlab.gnome.org/GNOME/gnome-shell-extensions", - "uuid": "user-theme@gnome-shell-extensions.gcampax.github.com", - "version": 57 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/prefs.js deleted file mode 100755 index 9b4cf951..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/prefs.js +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Florian Müllner -// -// SPDX-License-Identifier: GPL-2.0-or-later - -// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- - -// we use async/await here to not block the mainloop, not to parallelize -/* eslint-disable no-await-in-loop */ - -import Adw from 'gi://Adw'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; -import Gtk from 'gi://Gtk'; - -import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -import {getThemeDirs, getModeThemeDirs} from './util.js'; - -Gio._promisify(Gio.File.prototype, 'enumerate_children_async'); -Gio._promisify(Gio.File.prototype, 'query_info_async'); -Gio._promisify(Gio.FileEnumerator.prototype, 'next_files_async'); - -class UserThemePrefsWidget extends Adw.PreferencesGroup { - static { - GObject.registerClass(this); - } - - constructor(settings) { - super({title: 'Themes'}); - - this._actionGroup = new Gio.SimpleActionGroup(); - this.insert_action_group('theme', this._actionGroup); - - this._settings = settings; - this._actionGroup.add_action( - this._settings.create_action('name')); - - this.connect('destroy', () => (this._settings = null)); - - this._rows = new Map(); - this._addTheme(''); // default - - this._collectThemes(); - } - - async _collectThemes() { - for (const dirName of getThemeDirs()) { - const dir = Gio.File.new_for_path(dirName); - for (const name of await this._enumerateDir(dir)) { - if (this._rows.has(name)) - continue; - - const file = dir.resolve_relative_path( - `${name}/gnome-shell/gnome-shell.css`); - try { - await file.query_info_async( - Gio.FILE_ATTRIBUTE_STANDARD_NAME, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, null); - this._addTheme(name); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - logError(e); - } - } - } - - for (const dirName of getModeThemeDirs()) { - const dir = Gio.File.new_for_path(dirName); - for (const filename of await this._enumerateDir(dir)) { - if (!filename.endsWith('.css')) - continue; - - const name = filename.slice(0, -4); - if (!this._rows.has(name)) - this._addTheme(name); - } - } - } - - _addTheme(name) { - const row = new ThemeRow(name); - this._rows.set(name, row); - - this.add(row); - } - - async _enumerateDir(dir) { - const fileInfos = []; - let fileEnum; - - try { - fileEnum = await dir.enumerate_children_async( - Gio.FILE_ATTRIBUTE_STANDARD_NAME, - Gio.FileQueryInfoFlags.NONE, - GLib.PRIORITY_DEFAULT, null); - } catch (e) { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) - logError(e); - return []; - } - - let infos; - do { - infos = await fileEnum.next_files_async(100, - GLib.PRIORITY_DEFAULT, null); - fileInfos.push(...infos); - } while (infos.length > 0); - - return fileInfos.map(info => info.get_name()); - } -} - -class ThemeRow extends Adw.ActionRow { - static { - GObject.registerClass(this); - } - - constructor(name) { - const check = new Gtk.CheckButton({ - action_name: 'theme.name', - action_target: new GLib.Variant('s', name), - }); - - super({ - title: name || 'Default', - activatable_widget: check, - }); - this.add_prefix(check); - } -} - -export default class UserThemePrefs extends ExtensionPreferences { - getPreferencesWidget() { - return new UserThemePrefsWidget(this.getSettings()); - } -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/schemas/gschemas.compiled deleted file mode 100755 index 4e8a5ca9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/schemas/org.gnome.shell.extensions.user-theme.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/schemas/org.gnome.shell.extensions.user-theme.gschema.xml deleted file mode 100755 index cf2dc201..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/schemas/org.gnome.shell.extensions.user-theme.gschema.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - "" - Theme name - The name of the theme, to be loaded from ~/.themes/name/gnome-shell - - - diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/util.js b/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/util.js deleted file mode 100755 index e02b464e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/user-theme@gnome-shell-extensions.gcampax.github.com/util.js +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2020 Florian Müllner -// -// SPDX-License-Identifier: GPL-2.0-or-later - -import GLib from 'gi://GLib'; - -const fn = (...args) => GLib.build_filenamev(args); - -/** - * @returns {string[]} - an ordered list of theme directories - */ -export function getThemeDirs() { - return [ - fn(GLib.get_home_dir(), '.themes'), - fn(GLib.get_user_data_dir(), 'themes'), - ...GLib.get_system_data_dirs().map(dir => fn(dir, 'themes')), - ]; -} - -/** - * @returns {string[]} - an ordered list of mode theme directories - */ -export function getModeThemeDirs() { - return GLib.get_system_data_dirs() - .map(dir => fn(dir, 'gnome-shell', 'theme')); -} diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/extension.js b/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/extension.js deleted file mode 100644 index 224df977..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/extension.js +++ /dev/null @@ -1,2682 +0,0 @@ -/* extension.js - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -import Clutter from 'gi://Clutter'; -import Meta from 'gi://Meta'; -import St from 'gi://St'; -import Shell from 'gi://Shell'; -import Gio from 'gi://Gio'; - -import * as Main from 'resource:///org/gnome/shell/ui/main.js'; -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; - -// Window edge action -const WindowEdgeAction = { - NONE: 0, // No action - WAIT_GESTURE: 0x01, // Wait for gesture flag - MOVE: 0x02, // Move flag - RESIZE: 0x04, // Resize flag - - GESTURE_LEFT: 0x10, // Gesture Left - GESTURE_RIGHT: 0x20, // Gesture Right - GESTURE_UP: 0x40, // Gesture Up - GESTURE_DOWN: 0x80, // Gesture Down - - GESTURE_UP_LEFT: 0x100, // Gesture Up Left - GESTURE_UP_RIGHT: 0x200, // Gesture Up Right - - GESTURE_HORIZONTAL: 0x400, // Non-Window Gestures - GESTURE_VERTICAL: 0x800, - - RESIZE_LEFT: 0x1000, // Resize Flags - RESIZE_RIGHT: 0x2000, - RESIZE_TOP: 0x4000, - RESIZE_BOTTOM: 0x8000, - - MOVE_SNAP_TOP: 0x10000, // Snap Flags - MOVE_SNAP_LEFT: 0x20000, - MOVE_SNAP_RIGHT: 0x40000 - -}; - -// Window Blacklist Classes -const WindowClassBlacklist = [ - "gjs" -]; - -// Manager Class -class Manager { - - // Init Extension - constructor(ext) { - // Get settings - this._settings = ext.getSettings(); - - // Gestures are hooked by WGS - this._hooked = false; - - // Create virtual devices - const seat = Clutter.get_default_backend().get_default_seat(); - this._virtualTouchpad = seat.create_virtual_device( - Clutter.InputDeviceType.POINTER_DEVICE - ); - this._virtualKeyboard = seat.create_virtual_device( - Clutter.InputDeviceType.KEYBOARD_DEVICE - ); - - // Init variables - keep enable() clean - this._clearVars(); - - // Capture Touchpad Event - this._gestureCallbackID = global.stage.connect( - 'captured-event::touchpad', - this._touchpadEvent.bind(this) - ); - - // init 3 or 4 fingers config support - this._initFingerCountFlip(); - - // action widget holder - this._actionWidgets = {}; - - // Desktop Theme Setting - this._isettings = new Gio.Settings({ - schema: 'org.gnome.desktop.interface' - }); - } - - // Clear potentially running timeout/interval - destroyTimers() { - if (this._holdTo) { - // hold waiter - clearTimeout(this._holdTo); - this._holdTo = null; - } - if (this._actionWidgets.resetWinlist) { - // Alt+Tab timeout - clearTimeout(this._actionWidgets.resetWinlist); - this._actionWidgets.resetWinlist = null; - } - if (this._keyRepeatInterval) { - // Key repeat interval - clearInterval(this._keyRepeatInterval); - this._keyRepeatInterval = null; - } - if (this._flingInterval) { - // Kinetic interval - clearInterval(this._flingInterval); - this._flingInterval = null; - } - if (this._actionWidgets.tilerHider) { - clearTimeout(this._actionWidgets.tilerHider); - this._actionWidgets.tilerHider = null; - } - } - - // Cleanup Extension - destroy() { - // clear timers - this.destroyTimers(); - - // restore default GNOME 3 fingers gesture - this._restoreFingerCountFlip(); - - // Release Touchpad Event Capture - global.stage.disconnect(this._gestureCallbackID); - - // Cleanup virtual devices - this._virtualTouchpad = null; - this._virtualKeyboard = null; - - // Cleanup all variables - this._clearVars(); - this._isettings = null; - this._settings = null; - this._ShaderClass = null; - } - - // Initialize variables - _clearVars() { - // Target window to manage - this._targetWindow = null; - - // Mouse start position - this._startPos = { - x: 0, y: 0 - }; - - // Mouse start position - this._movePos = { - x: 0, y: 0 - }; - - // Monitor Id - this._monitorId = 0; - - // Monitor Workarea - this._monitorArea = null; - - // Starting Window Area - this._startWinArea = null; - - // Edge Action - this._edgeAction = WindowEdgeAction.NONE; - this._edgeGestured = 0; - this._swipeIsWin = false; - this._isActiveWin = false; - this._tapHold = 0; - this._tapHoldWin = null; - this._tapHoldTick = 0; - - // Pinch - this._gesture = { - begin: false, - fingers: 0, - progress: 0, - - velocity: null, - - action: 0, - action_id: 0, - action_cmp: 0 - }; - - // Clear window tile preview - // this._hidePreview(); - } - - // Init 3 or 4 finger count switch mode - _initFingerCountFlip() { - // Move 3-4 Finger Gesture - /* - * Original Hook Logic From (swap-finger-gestures): - * https://github.com/icedman/swap-finger-gestures-3-4 - * - */ - this._swipeMods = [ - Main.overview._swipeTracker._touchpadGesture, - Main.wm._workspaceAnimation._swipeTracker._touchpadGesture, - Main.overview._overview._controls - ._workspacesDisplay._swipeTracker._touchpadGesture, - Main.overview._overview._controls - ._appDisplay._swipeTracker._touchpadGesture - ]; - let me = this; - this._swipeMods.forEach((g) => { - g._newHandleEvent = (actor, event) => { - event._get_touchpad_gesture_finger_count = - event.get_touchpad_gesture_finger_count; - event.get_touchpad_gesture_finger_count = () => { - let real_count = event._get_touchpad_gesture_finger_count(); - if (me._hooked || (real_count == me._gestureNumFinger())) { - return 0; - } - else if (real_count >= 3) { - return 3; - } - return 0; - }; - if (me._hooked) { - return Clutter.EVENT_STOP; - } - return g._handleEvent(actor, event); - }; - global.stage.disconnectObject(g); - global.stage.connectObject( - 'captured-event::touchpad', - g._newHandleEvent.bind(g), - g - ); - }); - } - - // Restore 3 or 4 finger count switch mode - _restoreFingerCountFlip() { - // Restore 3 finger gesture - this._swipeMods.forEach((g) => { - global.stage.disconnectObject(g); - global.stage.connectObject( - 'captured-event::touchpad', - g._handleEvent.bind(g), - g - ); - }); - this._swipeMods = []; - } - - // Is dark theme? - _isDarkTheme() { - let uit = this._settings.get_int('ui-theme'); - if (uit == 0) { - return (this._isettings - .get_string('color-scheme') == 'prefer-dark'); - } - return (uit == 2); - } - - // Create UI Indicator - _createUi(ui_class, x, y, w, h, icon, parent) { - let ui = new St.Widget({ style_class: ui_class }); - if (this._isDarkTheme()) { - ui.add_style_class_name("wgs-dark"); - } - // ui.set_clip_to_allocation(true); - ui._icon = null; - ui._parent = parent ? parent : Main.layoutManager.uiGroup; - if (icon) { - ui._icon = new St.Icon({ - icon_name: icon, - style_class: 'wgs-widget-icon' - }); - ui.add_child(ui._icon); - } - ui.set_position(x, y); - ui.set_size(w, h); - ui.set_pivot_point(0.5, 0.5); - ui.viewShow = (prop, duration) => { - ui.show(); - prop.mode = Clutter.AnimationMode.EASE_OUT_QUAD; - prop.duration = duration; - ui.ease(prop); - }; - ui.viewHide = (prop) => { - prop.mode = Clutter.AnimationMode.EASE_OUT_QUAD; - prop.duration = duration; - prop.onStopped = () => { - ui.hide(); - }; - ui.ease(prop); - }; - ui.aniRelease = (progress) => { - if (!progress) { - progress = 1.0; - } - if (progress > 0.2) { - ui.ease({ - opacity: 0, - scale_x: 0, - scale_y: 0, - duration: Math.round(250 * progress), - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onStopped: () => { - ui.release(); - } - }); - } - else { - ui.release(); - } - }; - ui.release = () => { - // Cleanup - ui.hide(); - ui._parent.remove_child(ui); - if (ui._icon) { - ui.remove_child(ui._icon); - ui._icon.destroy(); - ui._icon = null; - } - ui.destroy(); - ui = null; - }; - ui._parent.add_child(ui); - return ui; - } - - // Create Shader Effect - _createShader(type, actor, name) { - let fx = new Clutter.ShaderEffect( - { shader_type: Clutter.ShaderType.FRAGMENT_SHADER } - ); - let shader = ''; - if (type == 'close') { - shader = - 'color.g *= 1-(0.3*value); ' + - 'color.b *= 1-(0.34*value); '; - } - else { - shader = - 'color.rgb *= 1.0-value; '; - } - fx.set_shader_source( - 'uniform sampler2D tex; ' + - 'uniform float value; ' + - 'void main() { ' + - 'vec4 color=texture2D(tex,cogl_tex_coord_in[0].st);' + - shader + - 'cogl_color_out = color * cogl_color_in;}' - ); - fx.set_uniform_value('tex', 0); - fx.setValue = function (v) { - fx.set_uniform_value('value', v); - } - if (actor) { - fx._fxname = name; - actor.fx = fx; - if (actor.get_effect(name)) { - actor.remove_effect_by_name(name); - } - actor.add_effect_with_name(name, fx); - } - fx.release = () => { - if (actor) { - actor.remove_effect_by_name(actor.fx._fxname); - actor.fx = null; - actor = null; - } - fx = null; - }; - return fx; - } - - // Velocity functions - _velocityInit() { - let vel = { - data: [], - prev: 0 - }; - return vel; - } - _velocityTrim(vel) { - const thresholdTime = this._tick() - 150; - const index = vel.data.findIndex(r => r.time >= thresholdTime); - vel.data.splice(0, index); - } - _velocityAppend(vel, v) { - this._velocityTrim(vel); - let vb = Math.abs(v); - let d = vb - vel.prev; - vel.prev = vb; - vel.data.push({ time: this._tick(), delta: d }); - } - _velocityCalc(vel) { - this._velocityTrim(vel); - if (vel.data.length < 2) - return 0; - const firstTime = vel.data[0].time; - const lastTime = vel.data[vel.data.length - 1].time; - if (firstTime === lastTime) - return 0; - const totalDelta = vel.data.slice(1).map( - a => a.delta).reduce((a, b) => a + b); - const period = lastTime - firstTime; - return totalDelta / period; - } - _velocityFlingHandler(me) { - if (me._velocityFlingQueue.length == 0) { - clearInterval(me._flingInterval); - me._flingInterval = 0; - return; - } - let now = me._velocityFlingQueue[0]; - let clearIt = false; - now.target += now.v * 2; - now.v *= 0.98; - now.n++; - if (me._velocityFlingQueue.length != 1) { - // Another fling called - now.cb(1, target); - clearIt = true; - } - else if (now.target >= now.max || now.n >= now.maxframe) { - if (now.target >= now.max) { - now.target = now.max; - } - now.cb(1, now.target); - clearIt = true; - } - else { - now.cb(0, now.target); - } - if (clearIt) { - me._velocityFlingQueue.splice(0, 1); - } - } - _velocityFling(vel, curr, max, maxframe, cb) { - if (!this._velocityFlingQueue) { - this._velocityFlingQueue = []; - } - this._velocityFlingQueue.push({ - target: curr, - v: vel, - max: max, - maxframe: maxframe, - cb: cb, - n: 0 - }); - if (!this._flingInterval) { - this._flingInterval = setInterval( - this._velocityFlingHandler, 4, this - ); - } - } - _tick() { - return new Date().getTime(); - } - - _isWindowBlacklist(win) { - if (win) { - if (WindowClassBlacklist.indexOf(win.get_wm_class()) == -1 || - win.get_window_type() === Meta.WindowType.DESKTOP) { - return false; - } - } - return true; - } - - // Get padding edge size - _edgeSize() { - return this._settings.get_int('edge-size'); - } - - // Get top padding edge size - _topEdgeSize() { - return this._settings.get_int('top-edge-size'); - } - - // Get gesture threshold - _gestureThreshold() { - return this._settings.get_int('gesture-threshold'); - } - - // Get acceleration - _getAcceleration() { - return (this._settings.get_int('gesture-acceleration') * 0.1); - } - - // Get gesture threshold - _gestureCancelThreshold() { - return this._settings.get_int('gesture-cancel-threshold'); - } - - // Is 3 Finger - _gestureNumFinger() { - return this._settings.get_boolean("three-finger") ? 3 : 4; - } - - // Functions Settings - _getUseActiveWindow() { - return this._settings.get_boolean("use-active-window"); - } - _getEnableResize() { - return this._settings.get_boolean("fn-resize"); - } - _getEnableMove() { - return this._settings.get_boolean("fn-move"); - } - _getEnableMaxSnap() { - return this._settings.get_boolean("fn-maximized-snap"); - } - _getEnableMoveSnap() { - return this._settings.get_boolean("fn-move-snap"); - } - _getEnableFullscreen() { - return this._settings.get_boolean("fn-fullscreen"); - } - _getPinchInScale() { - return this._settings.get_int('pinch-in-scale'); - } - _getPinchOutScale() { - return this._settings.get_int('pinch-out-scale'); - } - _getPinchEnabled() { - return this._settings.get_boolean("pinch-enable"); - } - _getTapHoldMove() { - return this._settings.get_boolean("taphold-move"); - } - - // Is On Overview - _isOnOverview() { - return Main.overview._shown; - } - - // Check edge flags - _isEdge(edge) { - return ((this._edgeAction & edge) == edge); - } - - // Show Preview - _showPreview(rx, ry, rw, rh) { - if (global.display.get_focus_window() == null) { - return; - } - global.window_manager.emit("show-tile-preview", - global.display.get_focus_window(), new Meta.Rectangle( - { x: rx, y: ry, width: rw, height: rh } - ) - , this._monitorId - ); - } - - // Find Target Window - _findPointerWindow() { - let target = null; - let [pointerX, pointerY, pointerZ] = global.get_pointer(); - let currActor = global.stage.get_actor_at_pos( - Clutter.PickMode.REACTIVE, pointerX, pointerY - ); - if (currActor) { - // Find root window for current actor - let currWindow = currActor.get_parent(); - let i = 0; - while (currWindow && !currWindow.get_meta_window) { - currWindow = currWindow.get_parent(); - if (!currWindow || (++i > 10)) { - currWindow = null; - break; - } - } - // Set meta window as target window to manage - target = currWindow?.get_meta_window(); - } - return target; - } - - // Get Alt Tabs List - _getWindowTabList() { - let wm = global.workspace_manager; - let workspace = wm.get_active_workspace(); - let windows = global.display.get_tab_list( - Meta.TabList.NORMAL_ALL, workspace - ); - return windows.map(w => { - return w.is_attached_dialog() ? w.get_transient_for() : w; - }).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) === i); - } - - // Hide Preview - _hidePreview() { - global.window_manager.emit("hide-tile-preview"); - } - - // Simulate keypress (up -> down) - _sendKeyPress(combination) { - combination.forEach(key => this._virtualKeyboard.notify_keyval( - Clutter.get_current_event_time(), key, Clutter.KeyState.PRESSED) - ); - combination.reverse().forEach(key => - this._virtualKeyboard.notify_keyval( - Clutter.get_current_event_time(), key, Clutter.KeyState.RELEASED - )); - } - - // Move Mouse Pointer - _movePointer(x, y) { - if (!this._isActiveWin) { - // Move only if not use active window - this._virtualTouchpad.notify_relative_motion( - Meta.CURRENT_TIME, x, y - ); - } - } - - // window management - _winmanWinApp(win) { - return Shell.WindowTracker.get_default() - .get_window_app(win); - // App.create_icon_texture; - } - - // Snap Window - _setSnapWindow(snapRight) { - if (this._targetWindow == null) { - return; - } - // TODO: Using non key shortcut for snap left/right - if (snapRight) { - this._sendKeyPress([Clutter.KEY_Super_L, Clutter.KEY_Right]); - } - else { - this._sendKeyPress([Clutter.KEY_Super_L, Clutter.KEY_Left]); - } - } - - // Move to Workspace - _moveWindowWorkspace(moveRight) { - if ((this._targetWindow == null) || - !Meta.prefs_get_dynamic_workspaces()) { - return; - } - let wsid = this._targetWindow.get_workspace().index(); - if (wsid == 0 && !moveRight) { - this._insertWorkspace(0, this._targetWindow); - return; - } - let tw = this._targetWindow.get_workspace() - .get_neighbor(moveRight ? Meta.MotionDirection.RIGHT : - Meta.MotionDirection.LEFT); - this._targetWindow.change_workspace(tw); - this._targetWindow.activate(Meta.CURRENT_TIME); - } - - // Insert new workspace - _insertWorkspace(pos, chkwin) { - // Main.wm.insertWorkspace(0); - let wm = global.workspace_manager; - if (!Meta.prefs_get_dynamic_workspaces()) { - return -1; - } - wm.append_new_workspace(false, Meta.CURRENT_TIME); - let windows = global.get_window_actors().map(a => a.meta_window); - windows.forEach(window => { - if (chkwin && chkwin == window) - return -1; - if (window.get_transient_for() != null) - return -1; - if (window.is_override_redirect()) - return -1; - if (window.on_all_workspaces) - return -1; - let index = window.get_workspace().index(); - if (index < pos) - return -1; - window.change_workspace_by_index(index + 1, true); - }); - if (chkwin) { - wm.get_workspace_by_index(pos + 1).activate( - Meta.CURRENT_TIME - ); - chkwin.change_workspace_by_index(pos, true); - this._targetWindow.activate(Meta.CURRENT_TIME); - } - return pos; - } - _isDynamicWorkspace() { - return Meta.prefs_get_dynamic_workspaces(); - } - - // Have Left Workspace - _workspaceHavePrev() { - if (this._targetWindow == null) { - return false; - } - return (this._targetWindow.get_workspace().index() > 0); - } - - _resetWinPos() { - if (this._targetWindow == null) { - return; - } - - // Reset - this._targetWindow.move_frame( - true, - this._startWinArea.x, - this._startWinArea.y - ); - } - - // Activate Target Window - _activateWindow() { - if (this._targetWindow == null) { - return; - } - - // Activate window if not focused yet - if (!this._targetWindow.has_focus()) { - this._targetWindow.activate( - Meta.CURRENT_TIME - ); - } - } - - // Swipe window move handler - _swipeUpdateMove() { - this._activateWindow(); - - // gnome-shell-extension-tiling-assistant support - if (this._targetWindow.isTiled) { - let urct = this._targetWindow.untiledRect; - if (urct) { - let r = urct._rect; - this._startWinArea.x = r.x; - this._startWinArea.y = r.y; - this._startWinArea.width = r.width; - this._startWinArea.height = r.height; - // this._targetWindow.move_resize_frame( - // true, - // r.x, r.y, r.width, r.height - // ); - this._sendKeyPress([Clutter.KEY_Super_L, Clutter.KEY_Down]); - } - } - - let allowMoveSnap = this._getEnableMoveSnap(); - // Move calculation - let mX = this._monitorArea.x; - let mY = this._monitorArea.y; - let mW = this._monitorArea.width; - let mR = mX + mW; - let winX = this._startWinArea.x + this._movePos.x; - let winY = this._startWinArea.y + this._movePos.y; - let winR = winX + this._startWinArea.width; - // Move action - this._targetWindow.move_frame( - true, - winX, winY - ); - if (allowMoveSnap && winX < mX) { - this._showPreview( - this._monitorArea.x, - this._monitorArea.y, - this._monitorArea.width / 2, - this._monitorArea.height - ); - this._edgeAction = WindowEdgeAction.MOVE - | WindowEdgeAction.MOVE_SNAP_LEFT; - } - else if (allowMoveSnap && winR > mR) { - this._showPreview( - this._monitorArea.x + (this._monitorArea.width / 2), - this._monitorArea.y, - this._monitorArea.width / 2, - this._monitorArea.height - ); - this._edgeAction = WindowEdgeAction.MOVE - | WindowEdgeAction.MOVE_SNAP_RIGHT; - } - else if (allowMoveSnap && winY < mY) { - this._showPreview( - this._monitorArea.x, - this._monitorArea.y, - this._monitorArea.width, - this._monitorArea.height - ); - this._edgeAction = WindowEdgeAction.MOVE - | WindowEdgeAction.MOVE_SNAP_TOP; - } - else { - this._edgeAction = WindowEdgeAction.MOVE; - this._hidePreview(); - } - return Clutter.EVENT_STOP; - } - - // Swipe window resize handler - _swipeUpdateResize(dx, dy) { - this._activateWindow(); - // Move cursor pointer - this._movePointer( - (this._isEdge(WindowEdgeAction.RESIZE_LEFT) || - this._isEdge(WindowEdgeAction.RESIZE_RIGHT)) ? dx : 0, - (this._isEdge(WindowEdgeAction.RESIZE_TOP) || - this._isEdge(WindowEdgeAction.RESIZE_BOTTOM)) ? dy : 0 - ); - // Resize actions - let tX = this._startWinArea.x; - let tY = this._startWinArea.y; - let tW = this._startWinArea.width; - let tH = this._startWinArea.height; - if (this._isEdge(WindowEdgeAction.RESIZE_BOTTOM)) { - tH += this._movePos.y; - } - else if (this._isEdge(WindowEdgeAction.RESIZE_TOP)) { - tY += this._movePos.y; - tH -= this._movePos.y; - } - if (this._isEdge(WindowEdgeAction.RESIZE_RIGHT)) { - tW += this._movePos.x; - } - else if (this._isEdge(WindowEdgeAction.RESIZE_LEFT)) { - tX += this._movePos.x; - tW -= this._movePos.x; - } - let tR = tX + tW; - let tB = tY + tH; - let mX = this._monitorArea.x; - let mY = this._monitorArea.y; - let mW = this._monitorArea.width; - let mH = this._monitorArea.height; - let mR = mX + mW; - let mB = mY + mH; - // edge - if (tX < mX) { - tX = mX; - tW = tR - tX; - } - if (tY < mY) { - tY = mY; - tH = tB - tY; - } - if (tR > mR) { - tW = mR - tX; - } - if (tB > mB) { - tH = mB - tY; - } - // Resize Window - this._targetWindow.move_resize_frame( - true, - tX, tY, tW, tH - ); - return Clutter.EVENT_STOP; - } - - // Begin swipe gesture - _swipeBegin(numfingers) { - // Swipe Variables - this._swipeIsWin = (numfingers == this._gestureNumFinger()); - - // Workspace gesture only not on overview - if (this._isOnOverview() && !this._swipeIsWin) { - return Clutter.EVENT_PROPAGATE; - } - - // Init gesture variables - this._gesture.begin = true; - this._gesture.fingers = numfingers; - this._gesture.progress = 0; - - // Action Variables - this._gesture.action = 0; - this._gesture.action_cmp = 0; - this._gesture.action_id = 0; - - // Velocity Variables - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - - // Get current mouse position - let [pointerX, pointerY, pointerZ] = global.get_pointer(); - this._startPos.x = pointerX; - this._startPos.y = pointerY; - this._movePos.x = this._movePos.y = 0; - - // Configs - let allowResize = this._getEnableResize(); - let allowMove = this._getEnableMove(); - this._isActiveWin = false; - this._targetWindow = null; - let isTapHoldAction = false; - - // Clear unswipe tap-hold - if ((this._tapHoldTick != 1) && - (this._tapHoldTick < this._tick())) { - this._tapHold = this._tapHoldTick = 0; - this._tapHoldWin = null; - } - - if (this._tapHoldWin) { - this._targetWindow = this._tapHoldWin; - this._tapHoldWin = null; - isTapHoldAction = true; - } - else if (!this._getUseActiveWindow() && !this._getTapHoldMove()) { - this._targetWindow = this._findPointerWindow(); - } - if (!this._targetWindow) { - // Get Active Window - this._targetWindow = global.display.get_focus_window(); - if (!this._targetWindow) { - return this._swipeIsWin ? - Clutter.EVENT_STOP : Clutter.EVENT_PROPAGATE; - } - allowResize = false; - this._isActiveWin = true; - } - - // Set opener window as target if it was dialog - if (this._targetWindow.is_attached_dialog()) { - this._targetWindow = this._targetWindow.get_transient_for(); - } - - // Check blacklist window - if (this._isWindowBlacklist(this._targetWindow)) { - this._targetWindow = null; - return this._swipeIsWin ? - Clutter.EVENT_STOP : Clutter.EVENT_PROPAGATE; - } - - // Get monitor area - this._monitorArea = this._targetWindow.get_work_area_current_monitor(); - - // Get monitor id - this._monitorId = global.display.get_monitor_index_for_rect( - this._monitorArea - ); - - // Get start frame rectangle - this._startWinArea = this._targetWindow.get_frame_rect(); - - // Window area as local value - let wLeft = this._startWinArea.x; - let wTop = this._startWinArea.y; - let wRight = wLeft + this._startWinArea.width; - let wBottom = wTop + this._startWinArea.height; - let wThirdX = wLeft + (this._startWinArea.width / 3); - let wThirdY = wTop + (this._startWinArea.height / 3); - let w34X = wLeft + ((this._startWinArea.width / 3) * 2); - let w34Y = wTop + ((this._startWinArea.height / 3) * 2); - - // Detect window edge - let edge = this._edgeSize(); - let topEdge = this._topEdgeSize(); - - // Default edge: need move event for more actions - this._edgeAction = WindowEdgeAction.NONE; - this._edgeGestured = 0; - - // Check allow resize - if (this._swipeIsWin && !this._isActiveWin && allowResize && - this._targetWindow.allows_resize() && - this._targetWindow.allows_move() && - !this._targetWindow.isTiled && !isTapHoldAction) { - // Edge cursor position detection - if (this._startPos.y >= wBottom - edge) { - if (this._startPos.y <= wBottom) { - // Cursor on bottom of window - this._edgeAction = - WindowEdgeAction.RESIZE | - WindowEdgeAction.RESIZE_BOTTOM; - - // 1/3 from left|right - if (this._startPos.x <= wThirdX) { - this._edgeAction |= WindowEdgeAction.RESIZE_LEFT; - } - else if (this._startPos.x >= w34X) { - this._edgeAction |= WindowEdgeAction.RESIZE_RIGHT; - } - } - } - else { - if (this._startPos.x >= wLeft && this._startPos.x <= wRight) { - if (this._startPos.x <= wLeft + edge) { - // Cursor on left side of window - this._edgeAction = - WindowEdgeAction.RESIZE | - WindowEdgeAction.RESIZE_LEFT; - } - else if (this._startPos.x >= wRight - edge) { - // Cursor on right side of window - this._edgeAction = - WindowEdgeAction.RESIZE | - WindowEdgeAction.RESIZE_RIGHT; - } - if (this._isEdge(WindowEdgeAction.RESIZE)) { - // 1/3 from top|bottom - if (this._startPos.y <= wThirdY) { - this._edgeAction |= WindowEdgeAction.RESIZE_TOP; - } - else if (this._startPos.y >= w34Y) { - this._edgeAction |= WindowEdgeAction.RESIZE_BOTTOM; - } - } - } - } - } - if (this._swipeIsWin && !this._isEdge(WindowEdgeAction.RESIZE)) { - let setmove = false; - if (this._getTapHoldMove()) { - if (this._tapHold == this._gestureNumFinger()) { - // Tap and hold - setmove = true; - } - } - else if (allowMove && - this._startPos.x <= wRight && - this._startPos.x >= wLeft && - this._startPos.y >= wTop && - this._startPos.y <= wTop + topEdge) { - // Mouse in top side of window - setmove = true; - } - if (setmove) { - if (this._targetWindow.allows_move() && - !this._targetWindow.get_maximized()) { - this._edgeAction = WindowEdgeAction.MOVE; - } - } - } else if (this._tapHold > 2 && - this._tapHold != this._gestureNumFinger()) { - this._edgeAction = WindowEdgeAction.GESTURE_DOWN; - this._movePos.y = (this._gestureThreshold() / 4) + 1; - } - - return this._swipeIsWin ? - Clutter.EVENT_STOP : Clutter.EVENT_PROPAGATE; - } - - _swipeUpdate(dx, dy) { - if (!this._gesture.begin) { - return Clutter.EVENT_PROPAGATE; - } - - // Moving coordinate - this._movePos.x += dx; - this._movePos.y += dy; - - // Move & Resize Handler - if (this._isEdge(WindowEdgeAction.MOVE)) { - return this._swipeUpdateMove(); - } - else if (this._isEdge(WindowEdgeAction.RESIZE)) { - return this._swipeUpdateResize(dx, dy); - } - - // Get threshold setting - let threshold = this._gestureThreshold(); - let combineTrigger = this._gestureThreshold() * 2; - let trigger = (threshold / 4) + 1; - let target = 1.00 * (trigger + (threshold * 10)); - let absX = Math.abs(this._movePos.x); - let absY = Math.abs(this._movePos.y); - - // Find gesture directions - if (this._edgeAction == WindowEdgeAction.NONE) { - if (absX >= trigger || absY >= trigger) { - if (absX > absY) { - if (this._movePos.x <= 0 - trigger) { - this._edgeAction = WindowEdgeAction.GESTURE_LEFT; - } - else if (this._movePos.x >= trigger) { - this._edgeAction = WindowEdgeAction.GESTURE_RIGHT; - } - this._movePos.y = 0; - } - else { - if (this._movePos.y <= 0 - trigger) { - this._edgeAction = WindowEdgeAction.GESTURE_UP; - } - else if (this._movePos.y >= trigger) { - this._edgeAction = WindowEdgeAction.GESTURE_DOWN; - if (this._swipeIsWin) { - let allowMove = this._getEnableMove(); - let holdMove = this._getTapHoldMove(); - - if (!allowMove || holdMove) { - if (!this._targetWindow.get_maximized() && - !this._targetWindow.isTiled) { - this._edgeGestured = 1; - } - else { - this._edgeGestured = 0; - } - } - else if ( - !this._edgeGestured && - !this._targetWindow.is_fullscreen() && - !this._targetWindow.get_maximized() && - this._targetWindow.allows_move()) { - this._edgeAction = WindowEdgeAction.MOVE; - return this._swipeUpdateMove(); - } - } - } - this._movePos.x = 0; - } - this._edgeGestured = this._edgeGestured ? 2 : 1; - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - } - } - - let prog = 0; - let vert = 0; - let horiz = 0; - if (this._isEdge(WindowEdgeAction.GESTURE_LEFT)) { - if (!this._swipeIsWin && !this._hooked) { - return Clutter.EVENT_PROPAGATE; - } - let xmove = this._movePos.x + trigger; - if (this._isEdge(WindowEdgeAction.GESTURE_UP) || - this._isEdge(WindowEdgeAction.GESTURE_DOWN)) { - xmove = this._movePos.x + combineTrigger; - } - else if (!this._swipeIsWin) { - return Clutter.EVENT_PROPAGATE; - } - if (xmove < 0) { - prog = Math.abs(xmove) / target; - } - horiz = 1; - } - else if (this._isEdge(WindowEdgeAction.GESTURE_RIGHT)) { - if (!this._swipeIsWin && !this._hooked) { - return Clutter.EVENT_PROPAGATE; - } - let xmove = this._movePos.x - trigger; - if (this._isEdge(WindowEdgeAction.GESTURE_UP) || - this._isEdge(WindowEdgeAction.GESTURE_DOWN)) { - xmove = this._movePos.x - combineTrigger; - } - else if (!this._swipeIsWin) { - return Clutter.EVENT_PROPAGATE; - } - if (xmove > 0) { - prog = xmove / target; - } - horiz = 2; - } - else if (this._isEdge(WindowEdgeAction.GESTURE_UP)) { - if (!this._swipeIsWin && !this._hooked) { - return Clutter.EVENT_PROPAGATE; - } - if (this._movePos.y < 0) { - prog = Math.abs(this._movePos.y) / target; - } - vert = 1; - } - else if (this._isEdge(WindowEdgeAction.GESTURE_DOWN)) { - if (!this._swipeIsWin && this._isOnOverview()) { - return Clutter.EVENT_PROPAGATE; - } - if (!this._swipeIsWin) { - this._hooked = true; - } - if (this._movePos.y > 0) { - let movey = this._movePos.y - (this._swipeIsWin ? - threshold : (threshold * 6)); - if (movey < 0) { - movey = 0; - } - prog = movey / target; - } - vert = 2; - } - - if (vert) { - if (absX >= trigger && ((vert == 1 && this._swipeIsWin) || - (vert == 2 && !this._swipeIsWin))) { - if (vert == 1 || prog == 0) { - // Combination gesture (Down + Left/Right) - if (this._movePos.x <= 0 - combineTrigger) { - this._edgeAction |= WindowEdgeAction.GESTURE_LEFT; - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - this._movePos.x = 0 - combineTrigger; - return this._swipeUpdate(0, 0); - } - else if (this._movePos.x >= combineTrigger) { - this._edgeAction |= WindowEdgeAction.GESTURE_RIGHT; - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - this._movePos.x = combineTrigger; - return this._swipeUpdate(0, 0); - } - } - } - } - else if (horiz) { - if (this._isEdge(WindowEdgeAction.GESTURE_UP)) { - vert = 1; - // Reset to single gesture - if (Math.abs(this._movePos.x) < combineTrigger) { - this._edgeAction = WindowEdgeAction.GESTURE_UP; - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - this._movePos.y = 0 - combineTrigger; - return this._swipeUpdate(0, 0); - } - } - else if (this._isEdge(WindowEdgeAction.GESTURE_DOWN)) { - vert = 2; - // Reset to single gesture - if (Math.abs(this._movePos.x) < combineTrigger) { - this._edgeAction = WindowEdgeAction.GESTURE_DOWN; - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - this._movePos.y = combineTrigger; - return this._swipeUpdate(0, 0); - } - } - } - - // Switch gestures direction - if ( - (vert == 1 && (this._movePos.y > 0 - trigger)) || - (vert == 2 && (this._movePos.y < 0)) || - (horiz == 1 && (this._movePos.x > 0 - trigger)) || - (horiz == 2 && (this._movePos.x < 0)) - ) { - if (!(this._isEdge(WindowEdgeAction.GESTURE_DOWN) && horiz)) { - if (vert) { - this._movePos.x = 0; - } - if (horiz) { - this._movePos.y = 0; - } - this._edgeAction = WindowEdgeAction.NONE; - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - return this._swipeUpdate(0, 0); - } - } - - // Limit progress - let oprog = prog; - if (prog >= 1) { - prog = 1.0; - } - this._gesture.action = 0; - - // Set action - if (vert == 0) { - this._gesture.action = horiz; // left=1, right=2 - } - else { - if (!this._swipeIsWin) { - if (horiz && vert == 2) { - // down + horiz - this._gesture.action = horiz + 4; // left=5, right=6 - } - else { - // vert - this._gesture.action = (vert == 2) ? 4 : 7; // d=4, u=7 - } - } - else { - if (horiz && vert == 1) { - // up + horiz - this._gesture.action = horiz + 50; // left=51, right=52 - } - else { - // vert - this._gesture.action = (vert == 2) ? - ((this._edgeGestured == 1) ? 53 : 3) : - 50; // up=50, dn=53, up+dn=3 - } - } - } - - // Cancel action - if (this._gesture.action_cmp && - (this._gesture.action != this._gesture.action_cmp)) { - // Send Cancel State - let aid = this._actionIdGet(this._gesture.action_cmp); - if (aid) { - this._runAction(aid, 1, 0); - } - } - - // Update progress & velocity - this._gesture.progress = prog; - this._velocityAppend(this._gesture.velocity, - this._gesture.progress); - - if (this._gesture.action) { - let aid = this._actionIdGet(this._gesture.action); - if (aid) { - if (aid >= 50) { - this._activateWindow(); - } - this._runAction(aid, 0, this._gesture.progress, oprog); - } - this._gesture.action_cmp = this._gesture.action; - } - - return Clutter.EVENT_STOP; - } - - _swipeEnd() { - // Check move snap - if (this._isEdge(WindowEdgeAction.MOVE)) { - this._hidePreview(); - if (this._isEdge(WindowEdgeAction.MOVE_SNAP_TOP)) { - if (this._targetWindow.can_maximize()) { - this._resetWinPos(); - this._targetWindow.maximize(Meta.MaximizeFlags.BOTH); - } - } - else if (this._isEdge(WindowEdgeAction.MOVE_SNAP_LEFT)) { - this._resetWinPos(); - this._setSnapWindow(0); - } - else if (this._isEdge(WindowEdgeAction.MOVE_SNAP_RIGHT)) { - this._resetWinPos(); - this._setSnapWindow(1); - } - this._hooked = false; - this._clearVars(); - return Clutter.EVENT_STOP; - } - - // Gesture Release - let retval = (!this._swipeIsWin && !this._hooked) ? - Clutter.EVENT_PROPAGATE : Clutter.EVENT_STOP; - this._hooked = false; - if (this._gesture.action) { - let aid = this._actionIdGet(this._gesture.action); - if (aid) { - let issnapaction = (aid == 51 || aid == 52); - if ((this._gesture.progress < 1.0) && !issnapaction) { - // Fling Velocity - let vel = this._velocityCalc(this._gesture.velocity); - if (vel > 0.001) { - let me = this; - this._velocityFling(vel, - this._gesture.progress, - 1.0, 30, - function (state, prog) { - me._runAction(aid, state, prog); - } - ); - this._clearVars(); - return retval; - } - } - this._runAction(aid, 1, this._gesture.progress); - } - } - this._clearVars(); - return retval; - } - - // Swipe Handler - _swipeEventHandler(actor, event) { - let numfingers = event.get_touchpad_gesture_finger_count(); - if (numfingers != 3 && numfingers != 4) { - return Clutter.EVENT_PROPAGATE; - } - // Process gestures state - switch (event.get_gesture_phase()) { - case Clutter.TouchpadGesturePhase.BEGIN: - // Begin event - return this._swipeBegin(numfingers); - case Clutter.TouchpadGesturePhase.UPDATE: - // Update / move event - let [dx, dy] = event.get_gesture_motion_delta(); - return this._swipeUpdate( - dx * this._getAcceleration(), - dy * this._getAcceleration() - ); - } - return this._swipeEnd(); - } - - // Get Current Action Id - _pinchGetCurrentActionId() { - if (this._gesture.begin && this._gesture.action != 0) { - if (this._gesture.action != this._gesture.action_cmp) { - this._gesture.action_id = this._actionIdGet( - (this._gesture.fingers == 3) ? - this._gesture.action + 7 : - this._gesture.action + 9 - ); - this._gesture.action_cmp = this._gesture.action; - } - return this._gesture.action_id; - } - return 0; - } - - // Update Pinch - _pinchUpdate(pinch_scale) { - if (this._gesture.begin) { - let pIn = (this._getPinchInScale() / 100.0); - let pOut = (this._getPinchOutScale() / 100.0); - - // Get prediction action & current progress position - if (pinch_scale < 1.0) { - if (pinch_scale < pIn) { - pinch_scale = pIn; - } - this._gesture.action = 1; - this._gesture.progress = (1.0 - pinch_scale) / (1.0 - pIn); - } - else if (pinch_scale > 1.0) { - if (pinch_scale > pOut) { - pinch_scale = pOut; - } - this._gesture.action = 2; - this._gesture.progress = (pinch_scale - 1.0) / (pOut - 1.0); - } - else { - this._gesture.action = 0; - this._gesture.progress = 0; - } - - if (this._gesture.action_cmp && - (this._gesture.action != this._gesture.action_cmp)) { - // Send Cancel State - let aid = this._actionIdGet( - (this._gesture.fingers == 3) ? - this._gesture.action_cmp + 7 : - this._gesture.action_cmp + 9 - ); - if (aid) { - this._runAction(aid, 1, 0); - } - - // Reset velocity - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - } - this._velocityAppend(this._gesture.velocity, - this._gesture.progress); - - let action_id = this._pinchGetCurrentActionId(); - if (action_id) { - this._runAction(action_id, 0, - this._gesture.progress - ); - } - } - return Clutter.EVENT_STOP; - } - - // Pinch Begin - _pinchBegin(numfingers) { - // Pinch Variables - this._gesture.begin = true; - this._gesture.fingers = numfingers; - this._gesture.progress = 0; - - // Action Variables - this._gesture.action = 0; - this._gesture.action_cmp = 0; - this._gesture.action_id = 0; - - // Velocity Variables - this._gesture.velocity = this._velocityInit(); - this._velocityAppend(this._gesture.velocity, 0); - return Clutter.EVENT_STOP; - } - - // End Pinch - _pinchEnd() { - let action_id = this._pinchGetCurrentActionId(); - if (action_id) { - if (this._gesture.progress < 1.0) { - // Fling Velocity - let vel = this._velocityCalc(this._gesture.velocity); - if (vel > 0.001) { - let me = this; - this._velocityFling(vel, - this._gesture.progress, - 1.0, 30, - function (state, prog) { - me._runAction(action_id, state, prog); - } - ); - this._clearVars(); - return Clutter.EVENT_STOP; - } - } - this._runAction(action_id, 1, this._gesture.progress); - } - this._clearVars(); - return Clutter.EVENT_STOP; - } - - // Pinch Handler - _pinchEventHandler(actor, event) { - if (!this._getPinchEnabled()) { - return Clutter.EVENT_PROPAGATE; - } - let numfingers = event.get_touchpad_gesture_finger_count(); - if (numfingers != 3 && numfingers != 4) { - return Clutter.EVENT_PROPAGATE; - } - const pinch_scale = event.get_gesture_pinch_scale(); - - // Process gestures state - switch (event.get_gesture_phase()) { - case Clutter.TouchpadGesturePhase.BEGIN: - return this._pinchBegin(numfingers); - case Clutter.TouchpadGesturePhase.UPDATE: - return this._pinchUpdate(pinch_scale); - } - return this._pinchEnd(); - } - - _tapHoldGesture(state, numfingers) { - let isWin = (numfingers == this._gestureNumFinger()); - if (!isWin || this._getTapHoldMove()) { - if (state) { - let me = this; - this._holdTo = setTimeout(function () { - me._tapHold = 0; - let activeWin = null; - if (!me._getUseActiveWindow()) { - activeWin = me._findPointerWindow(); - } - if (!activeWin) { - activeWin = global.display.get_focus_window(); - } - if (activeWin && ((activeWin.allows_move() && - !activeWin.get_maximized()) || !isWin)) { - activeWin.activate( - Meta.CURRENT_TIME - ); - me._tapHold = numfingers; - me._tapHoldWin = activeWin; - me._tapHoldTick = 1; - activeWin.get_compositor_private() - .set_pivot_point(0.5, 0.5); - activeWin.get_compositor_private().ease({ - duration: 100, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - scale_y: 1.05, - scale_x: 1.05, - onStopped: () => { - activeWin?.get_compositor_private().ease({ - duration: 100, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - scale_y: 1, - scale_x: 1, - onStopped: () => { - activeWin?.get_compositor_private() - .set_pivot_point(0, 0); - } - }); - } - }); - } - }, 100); - } - else { - if (this._holdTo) { - clearTimeout(this._holdTo); - } - this._tapHoldTick = this._tick() + 100; - this._holdTo = 0; - } - } - return Clutter.EVENT_PROPAGATE; - } - _tapHoldHandler(actor, event) { - // Process gestures state - let numfingers = event.get_touchpad_gesture_finger_count(); - if (numfingers != 3 && numfingers != 4) { - return Clutter.EVENT_PROPAGATE; - } - if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.BEGIN) { - return this._tapHoldGesture(1, numfingers); - } - return this._tapHoldGesture(0, numfingers); - } - - // Touch Event Handler - _touchpadEvent(actor, event) { - // log("_touchpadEvent = " + event.type()); - // Process pinch - if (event.type() == Clutter.EventType.TOUCHPAD_PINCH) - return this._pinchEventHandler(actor, event); - - // Process swipe - if (event.type() == Clutter.EventType.TOUCHPAD_SWIPE) - return this._swipeEventHandler(actor, event); - - // Process tap hold - if (event.type() == Clutter.EventType.TOUCHPAD_HOLD) - return this._tapHoldHandler(actor, event); - - return Clutter.EVENT_PROPAGATE; - } - - // Get Action Id - _actionIdGet(type) { - let cfg_name = ""; - switch (type) { - case 1: cfg_name = "swipe4-left"; break; - case 2: cfg_name = "swipe4-right"; break; - case 3: cfg_name = "swipe4-updown"; break; - case 4: cfg_name = "swipe3-down"; break; - case 5: cfg_name = "swipe3-left"; break; - case 6: cfg_name = "swipe3-right"; break; - case 7: cfg_name = "swipe3-downup"; break; - case 8: cfg_name = "pinch3-in"; break; - case 9: cfg_name = "pinch3-out"; break; - case 10: cfg_name = "pinch4-in"; break; - case 11: cfg_name = "pinch4-out"; break; - default: - if (type >= 50 && type <= 53) { - // Max & Snap - return type; - } - return 0; - } - return this._settings.get_int(cfg_name); - } - - // Run Action - _runAction(id, state, progress, oprog) { - const _LCASE = 32; - if (id == 1) { - // - // MINIMIZE ACTION - // - if (this._isOnOverview()) { - return; // Ignore on overview - } - - let activeWin = null; - let ui = this._actionWidgets.minimize; - - // Init indicator - if (!ui) { - activeWin = global.display.get_focus_window(); - if (this._isWindowBlacklist(activeWin)) { - activeWin = null; - } - if (activeWin && activeWin.can_minimize()) { - ui = activeWin.get_compositor_private(); - this._actionWidgets.minimize = ui; - if (ui) { - ui.set_pivot_point(0.5, 1); - } - } - else { - this._actionWidgets.minimize = ui = -1; - } - } - - // Execute Progress - if (ui && ui != -1) { - if (!state) { - ui.set_pivot_point(0.5, 1); - ui.opacity = 255 - Math.round(100 * progress); - ui.scale_x = 1.0 - (0.2 * progress); - ui.scale_y = 1.0 - (0.2 * progress); - } - else { - // Action is executed - activeWin = null; - if (progress >= 1.0) { - activeWin = global.display.get_focus_window(); - if (activeWin) { - if (!activeWin.can_minimize()) { - activeWin = null; - } - } - } - - // Restore - ui.ease({ - duration: Math.round(250 * progress), - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - opacity: activeWin ? 0 : 255, - scale_x: activeWin ? 0 : 1, - scale_y: activeWin ? 0 : 1, - onStopped: () => { - ui.set_pivot_point(0, 0); - if (activeWin) { - activeWin.minimize(); - ui.opacity = 0; - ui.ease({ - duration: 800, - opacity: 0, - onStopped: () => { - ui.opacity = 255; - ui.scale_x = 1; - ui.scale_y = 1; - ui = null; - } - }); - } - else { - ui = null; - } - } - }); - this._actionWidgets.minimize = null; - } - } else if (state) { - this._actionWidgets.minimize = ui = null; - } - } - else if (id == 2) { - // - // CLOSE WINDOW ACTION - // - if (this._isOnOverview()) { - return; // Ignore on overview - } - - let activeWin = null; - let ui = this._actionWidgets.close; - - // Init indicator - if (!ui) { - activeWin = global.display.get_focus_window(); - if (this._isWindowBlacklist(activeWin)) { - activeWin = null; - } - if (activeWin) { - ui = activeWin.get_compositor_private(); - this._actionWidgets.close = ui; - if (ui) { - ui.set_pivot_point(0.5, 0.5); - this._createShader('close', ui, 'closeindicator'); - ui.fx?.setValue(0); - } - } - else { - this._actionWidgets.close = ui = -1; - } - } - - // Execute Progress - if (ui && ui != -1) { - if (!state) { - ui.set_pivot_point(0.5, 0.5); - ui.opacity = 255 - Math.round(40 * progress); - ui.scale_x = 1.0 - (progress * 0.08); - ui.scale_y = 1.0 - (progress * 0.08); - ui.fx?.setValue(progress * 0.99); - } - else { - activeWin = null; - - // Action is executed - if (progress >= 1.0) { - activeWin = global.display.get_focus_window(); - } - - ui.fx?.release(); - ui.set_pivot_point(0, 0); - ui.opacity = 255; - ui.scale_x = 1.0; - ui.scale_y = 1.0; - if (activeWin) { - activeWin.delete( - Meta.CURRENT_TIME - ); - activeWin = null; - } - ui = null; - this._actionWidgets.close = null; - } - } else if (state) { - this._actionWidgets.close = ui = null; - } - } - else if (id == 3) { - // - // SHOW DESKTOP - // - if (this._isOnOverview()) { // Ignore on overview - return; - } - - let ui = this._actionWidgets.show_desktop; - - // Init indicator - if (!ui) { - let monitorArea = global.display.list_all_windows(); - if (monitorArea.length > 0) { - ui = []; - for (var i = 0; i < monitorArea.length; i++) { - if (!this._isWindowBlacklist(monitorArea[i])) { - let aui = monitorArea[i].get_compositor_private(); - - if (aui) { - ui.push(aui); - let mrect = monitorArea[i] - .get_work_area_current_monitor(); - let wrect = monitorArea[i].get_frame_rect(); - - // black magic calc ;) - let wl = (mrect.width / 32); - aui._t_targetx = (mrect.width - wl) - wrect.x; - var nx = (0 - (wrect.width - wl)) - wrect.x; - aui.set_pivot_point(1.0, 0.5); - if (Math.abs(nx) < Math.abs(aui._t_targetx)) { - aui._t_targetx = nx; - aui.set_pivot_point(1, (i % 5) * 0.25); - } - else { - aui.set_pivot_point(0, (i % 5) * 0.25); - } - } - } - } - this._actionWidgets.show_desktop = ui; - } - else { - this._actionWidgets.show_desktop = ui = -1; - } - } - - // Execute Progress - if (ui && ui != -1) { - if (!state) { - ui.forEach((aui) => { - aui.opacity = 255 - Math.round(180 * progress); - aui.scale_y = - aui.scale_x = 1.0 - (progress * 0.6); - aui.translation_x = ( - (progress * progress) * aui._t_targetx - ); - }); - } - else { - // Action is executed - if (progress >= 1.0) { - // Show Desktop (Super+D) Clutter.KEY_D - this._sendKeyPress( - [Clutter.KEY_Super_L, - Clutter.KEY_D + _LCASE] - ); - } - - ui.forEach((aui) => { - aui.ease({ - duration: Math.round(250 * progress), - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - opacity: 255, - translation_x: 0, - scale_x: 1, - scale_y: 1, - onStopped: () => { - aui.set_pivot_point(0, 0); - delete aui._t_targetx; - delete aui._t_targety; - } - }); - }); - - this._actionWidgets.show_desktop = ui = null; - } - } else if (state) { - this._actionWidgets.show_desktop = ui = null; - } - - } - else if ((id == 4) || (id == 5)) { - // - // NEXT & PREVIOUS WINDOW SWITCHING - // - if (this._isOnOverview()) { - return; // Ignore on overview - } - - let prv = (id == 5); - let wid = prv ? "switchwin_prev" : "switchwin_next"; - let ui = this._actionWidgets[wid]; - - // Init indicator - if (!ui) { - ui = -1; - let wins = null; - let listActor = null; - - // Cancel cache win timeout - if (this._actionWidgets.resetWinlist) { - clearTimeout(this._actionWidgets.resetWinlist); - this._actionWidgets.resetWinlist = 0; - } - // Get cached window list - if (this._actionWidgets.cacheWinTabList) { - wins = this._actionWidgets.cacheWinTabList?.wins; - listActor = this._actionWidgets.cacheWinTabList?.actor; - } - if (!wins) { - // No last cached - wins = this._getWindowTabList(); - if (wins.length > 1) { - // Create UI - let gsize = Main.layoutManager.uiGroup.get_size(); - let pad = 8; - let posCfg = this._settings.get_int( - 'winswitch-position' - ); - let lW = (pad * 2) + (wins.length * 48); - let lH = (pad * 2) + 32; - let lX = (gsize[0] - lW) / 2; - let lY = 64; // Top - let pivY = 0; - if (posCfg == 1) { - // Center - lY = (gsize[1] - lH) / 2; - pivY = 0.5; - } - else if (posCfg == 2) { - // Bottom - lY = gsize[1] - (lH + 64); - pivY = 1; - } - listActor = this._createUi( - "wgs-winswitch", lX, lY, lW, lH - ); - listActor.set_pivot_point(0.5, pivY); - listActor.opacity = 0; - listActor.scale_x = 0.5; - listActor.scale_y = 0.5; - listActor._data = []; - for (var i = 0; i < wins.length; i++) { - let win = wins[i]; - let app = this._winmanWinApp(win); - let ico = app.create_icon_texture(32); - ico.add_style_class_name("wgs-winswitch-ico"); - // remove_style_class_name - listActor.add_child(ico); - ico.set_size(32, 32); - ico.set_position((pad * 2) + (48 * i), pad); - ico.set_pivot_point(0.5, 0.5); - listActor._data.push( - { - app: app, - win: win, - ico: ico - } - ) - } - listActor.viewShow({ - opacity: 255, - scale_x: 1, - scale_y: 1 - }, 200); - - // Reorder for next (below 1s) calls - this._actionWidgets.cacheWinTabList = { - sel: 0, - first: wins[0], - wins: wins, - actor: listActor - }; - } - else { - this._actionWidgets.cacheWinTabList = null; - } - } - if (wins.length > 1) { - ui = { from: wins[0] }; - if (prv) { - ui.into = wins[wins.length - 1]; - ui.nsel = -1; - } - else { - ui.into = wins[1]; - ui.nsel = 1; - } - ui.lstate = 0; - ui.from_actor = ui.from.get_compositor_private(); - ui.into_actor = ui.into.get_compositor_private(); - ui.from_actor.set_pivot_point(0.5, 1); - ui.into_actor.set_pivot_point(0.5, 1); - - // Set selected target - for (var i = 0; i < listActor._data.length; i++) { - let d = listActor._data[i]; - if (d.win == ui.from) { - d.ico.add_style_class_name("selected"); - ui.from_ico = d.ico; - } - else if (d.win == ui.into) { - d.ico.remove_style_class_name("selected"); - ui.into_ico = d.ico; - } - else { - d.ico.remove_style_class_name("selected"); - } - } - } - this._actionWidgets[wid] = ui; - } - if (ui && ui != -1) { - if (!state) { - try { - ui.from_actor.opacity = 255 - Math.round(80 * progress); - ui.from_actor.scale_y = - ui.from_actor.scale_x = 1.0 - (0.05 * progress); - ui.into_actor.scale_y = - ui.into_actor.scale_x = 1.0 + (0.05 * progress); - } catch (e) { } - if (progress > 0.8) { - if (!ui.lstate) { - try { - ui.into.raise(); - } catch (e) { } - ui.lstate = 1; - ui.from_ico?.remove_style_class_name("selected"); - ui.into_ico?.add_style_class_name("selected"); - } - } - else if (ui.lstate) { - try { - ui.from.raise(); - } catch (e) { } - ui.lstate = 0; - ui.from_ico?.add_style_class_name("selected"); - ui.into_ico?.remove_style_class_name("selected"); - } - } - else { - if ((progress > 0.8) || ui.lstate) { - try { - try { - this._actionWidgets - .cacheWinTabList.first.activate( - Meta.CURRENT_TIME - ); - } catch (e) { } - try { - ui.from.raise(); - } catch (e) { } - ui.into.activate( - Meta.CURRENT_TIME - ); - } catch (e) { } - if (prv) { - this._actionWidgets.cacheWinTabList.wins.unshift( - this._actionWidgets.cacheWinTabList.wins.pop() - ); - } - else { - this._actionWidgets.cacheWinTabList.wins.push( - this._actionWidgets.cacheWinTabList.wins.shift() - ); - } - ui.from_ico?.remove_style_class_name("selected"); - ui.into_ico?.add_style_class_name("selected"); - } - else { - ui.from_ico?.add_style_class_name("selected"); - ui.into_ico?.remove_style_class_name("selected"); - } - ui.nclose = 0; - // Ease Restore - try { - ui.from_actor.ease({ - duration: Math.round(200 * progress), - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - opacity: 255, - scale_x: 1, - scale_y: 1, - onStopped: () => { - ui.from_actor.set_pivot_point(0, 0); - ui.from_actor = null; - ui.from = null; - if (++ui.nclose == 2) { - ui = null; - } - } - }); - } catch (e) { } - try { - ui.into_actor.ease({ - duration: Math.round(200 * progress), - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - opacity: 255, - scale_x: 1, - scale_y: 1, - onStopped: () => { - ui.into_actor.set_pivot_point(0, 0); - ui.into_actor = null; - ui.into = null; - if (++ui.nclose == 2) { - ui = null; - } - } - }); - } catch (e) { } - this._actionWidgets[wid] = null; - - // Clear cache after timeout - let me = this; - this._actionWidgets.resetWinlist = setTimeout( - function () { - me._actionWidgets - .cacheWinTabList.actor.aniRelease(); - me._actionWidgets.cacheWinTabList = null; - clearTimeout(me._actionWidgets.resetWinlist); - me._actionWidgets.resetWinlist = 0; - }, 500 - ); - } - } else if (state) { - this._actionWidgets[wid] = ui = null; - } - } - - else if ((id == 6) || (id == 7)) { - // - // SEND WINDOW LEFT/RIGHT WORKSPACE - // - if (this._isOnOverview()) { - return; // Ignore on overview - } - - let prv = (id == 6); - let wid = prv ? "movewin_left" : "movewin_right"; - let ui = this._actionWidgets[wid]; - let activeWin = null; - - // Init indicator - if (!ui) { - ui = -1; - let isDynamic = this._isDynamicWorkspace(); - activeWin = global.display.get_focus_window(); - let inserted = 0; - if (activeWin) { - let wsid = activeWin.get_workspace().index(); - let tsid = wsid; - if (prv) { - if (isDynamic) { - if (wsid == 0) { - let wpl = activeWin.get_workspace().list_windows(); - inserted = wpl.length; - if (inserted > 1) { - // Check for blacklisted windows - for (var i = 0; i < inserted; i++) { - if (this._isWindowBlacklist(wpl[i])) { - inserted--; - } - } - } - wsid = tsid = 1; - } - } - else { - if (wsid == 0) { - inserted = 1; - } - } - tsid--; - } - else { - if (!isDynamic && (wsid >= - global.workspace_manager.get_n_workspaces() - 1)) { - inserted = 1; - } - tsid++; - } - // Make sure move left from left-most workspace only - // triggered if other window is available in - // current workspace - if (inserted !== 1) { - activeWin.stick(); - if (inserted) { - this._insertWorkspace(0); - } - ui = { - confirmSwipe: () => { }, - wm: Main.wm._workspaceAnimation, - win: activeWin, - wid: tsid, - sid: wsid, - ins: inserted - }; - ui.wm._switchWorkspaceBegin( - ui, - global.display.get_primary_monitor() - ); - } - } - this._actionWidgets[wid] = ui; - } - if (ui && ui != -1) { - if (!state) { - ui.wm._switchWorkspaceUpdate( - ui, - ui.sid + ((prv) ? 0 - progress : progress) - ) - } - else { - ui.win.unstick(); - ui.wm._switchWorkspaceEnd( - ui, 350, - ui.sid + ((prv) ? 0 - progress : progress) - ); - if (progress > 0.5) { - ui.win.change_workspace_by_index( - ui.wid, true - ); - global.workspace_manager.get_workspace_by_index(ui.wid) - .activate( - Meta.CURRENT_TIME - ); - } - else if (ui.ins) { - // list_windows - if (ui.ins > 1) { - ui.win.change_workspace_by_index( - ui.sid, true - ); - } - else { - ui.win.change_workspace_by_index( - ui.wid, true - ); - } - } - ui.win.activate(Meta.CURRENT_TIME); - this._actionWidgets[wid] = ui = null; - } - } else if (state) { - this._actionWidgets[wid] = ui = null; - } - } - - else if (id >= 8 && id <= 9) { - // - // BACK / FORWARD - // - if (this._isOnOverview()) { - return; // Ignore on overview - } - - const keyList = [ - Clutter.KEY_Back, - Clutter.KEY_Forward - ]; - let kid = id - 8; - let activeWin = null; - let kidw = kid ? 'btnforward' : 'btnback'; - let ui = this._actionWidgets[kidw]; - - // Init indicator - if (!ui) { - activeWin = global.display.get_focus_window(); - if (this._isWindowBlacklist(activeWin)) { - activeWin = null; - } - if (activeWin) { - let uipar = activeWin.get_compositor_private(); - if (uipar) { - let wrect = activeWin.get_frame_rect(); - let uix = ((uipar.get_width() - wrect.width) / 2); - let uiy = (uipar.get_height() / 2) - 32; - if (kid) { - uix += wrect.width - 128; - } - else { - uix += 64; - } - ui = this._createUi( - 'wgs-indicator-backforward', - uix, - uiy, - 64, 64, - kid ? 'pan-end-symbolic.symbolic' : - 'pan-start-symbolic.symbolic', - uipar - ); - if (ui) { - ui.translation_x = kid ? -32 : 32; - ui.opacity = 0; - } - else { - ui = -1; - } - this._actionWidgets[kidw] = ui; - } - else { - this._actionWidgets[kidw] = -1; - } - } - else { - this._actionWidgets[kidw] = -1; - } - } - - // Execute Progress - if (ui && ui != -1) { - if (!state) { - if (kid) { - ui.translation_x = 32 - (32 * progress); - } - else { - ui.translation_x = (32 * progress) - 32; - } - ui.opacity = Math.round(255 * progress); - } - else { - // Action is executed - if (progress >= 1.0) { - this._sendKeyPress([keyList[kid]]); - } - ui.release(); - this._actionWidgets[kidw] = ui = null; - } - } else if (state) { - this._actionWidgets[kidw] = ui = null; - } - } - else if (id >= 10 && id <= 17) { - // - // MEDIA & BRIGHTNESS - // - const keyList = [ - Clutter.KEY_MonBrightnessUp, - Clutter.KEY_MonBrightnessDown, - Clutter.KEY_AudioRaiseVolume, - Clutter.KEY_AudioLowerVolume, - Clutter.KEY_AudioMute, - Clutter.KEY_AudioPlay, - Clutter.KEY_AudioNext, - Clutter.KEY_AudioPrev - ]; - let wid = 'keys_' + id; - let cid = 'keysn_' + id; - let keyId = keyList[id - 10]; - let isRepeat = (id < 14); - let kidw = 'keyaction_' + id; - let ui = this._actionWidgets[kidw]; - - if (isRepeat) { - if (!state && (progress >= 1)) { - if (!this._keyRepeatInterval) { - this._actionWidgets[cid] = 0; - this._sendKeyPress([keyId]); - this._keyRepeatInterval = setInterval( - function (me, cid, keyId) { - if (me._actionWidgets[cid] >= 5) { - me._sendKeyPress([keyId]); - } - else { - me._actionWidgets[cid]++; - } - }, - 100, - this, cid, keyId - ); - } - } - if (state) { - if (this._keyRepeatInterval) { - clearInterval(this._keyRepeatInterval); - } - this._keyRepeatInterval = 0; - this._actionWidgets[cid] = 0; - } - } - else { - if (!ui) { - const iconlist = [ - 'audio-volume-muted-symbolic', - 'media-playback-start-symbolic', - 'media-skip-forward-symbolic', - 'media-skip-backward-symbolic' - ]; - let display = global.get_display(); - let mrect = display.get_monitor_geometry( - display.get_primary_monitor() - ); - ui = this._createUi( - 'wgs-indicator-keys', - mrect.x + (mrect.width / 2) - 64, - mrect.y + (mrect.height / 2) - 64, - 128, 128, - iconlist[id - 14], - null - ); - ui.opacity = 0; - ui.scale_x = ui.scale_y = 0; - this._actionWidgets[kidw] = ui; - } - - // Execute Progress - if (ui && ui != -1) { - if (!state) { - ui.scale_x = ui.scale_y = progress; - ui.opacity = Math.round(255 * progress); - } - else { - // Action is executed - if (progress >= 1.0) { - this._sendKeyPress([keyId]); - } - ui.aniRelease(progress); - this._actionWidgets[kidw] = ui = null; - } - } - else if (state) { - this._actionWidgets[kidw] = ui = null; - } - } - - } - - // - // Non animated actions - // - else if (id == 18) { - if (this._isOnOverview()) { - // Ignore on overview - return; - } - if (!state || progress < 1.0) { - // Ignore if non end - return; - } - // ALT+TAB - this._sendKeyPress([Clutter.KEY_Alt_L, Clutter.KEY_Tab]); - } - else if (id == 19 || id == 20) { - if (!state || progress < 1.0) { - // Ignore if non end - return; - } - if (id == 19) { - Main.overview.show(); - } - else { - Main.overview.showApps(); - } - } - else if (id == 21) { - if (!state || progress < 1.0) { - // Ignore if non end - return; - } - // Quick Settings (Super+S) - Main.wm._toggleQuickSettings(); - // this._sendKeyPress([Clutter.KEY_Super_L, Clutter.KEY_S + _LCASE]); - } - else if (id == 22) { - if (!state || progress < 1.0) { - // Ignore if non end - return; - } - // Notification (Super+V) - Main.wm._toggleCalendar(); - // this._sendKeyPress([Clutter.KEY_Super_L, Clutter.KEY_V + _LCASE]); - } - else if (id == 23) { - if (!state || progress < 1.0) { - // Ignore if non end - return; - } - // Run (Alt+F2) - this._sendKeyPress([Clutter.KEY_Alt_L, Clutter.KEY_F2]); - } - - else if (id >= 50 && id <= 53) { - // - // Maximized, Fullscreen, Spap Etc. - // - let activeWin = global.display.get_focus_window(); - if (!activeWin || this._isOnOverview()) { - return; // Ignore on overview & no active window - } - if (this._isWindowBlacklist(activeWin)) { - return; // Ignore blacklisted - } - - let winCanMax = activeWin.allows_move() && activeWin.can_maximize(); - let winIsMaximized = activeWin.get_maximized(); - let winMaxed = Meta.MaximizeFlags.BOTH == winIsMaximized; - if (activeWin.isTiled) { - winIsMaximized = Meta.MaximizeFlags.VERTICAL; - } - let winIsFullscreen = activeWin.is_fullscreen(); - let allowFullscreen = this._getEnableFullscreen(); - let ui = 0; // find action id - if (id < 53) { - // Maximize - if (winMaxed) { - if (winIsFullscreen) { - ui = 5; // un-fullscreen - } - else if (allowFullscreen) { - ui = 4; // fullscreen - } - else { - ui = 6; // if not allow fullscreen (restore) - } - } - else if (winCanMax) { - // 1. Max, 2. Snap Left, 3. Snap Right - ui = id - 49; - } - } - else if (winIsFullscreen) { - ui = 5; // un-fullscreen - } - else if (winIsMaximized) { - ui = 6; // restore - } - let wid = "wmax_state" + ui; - - if (ui) { - if (!state) { - if (ui == 4) { - // fullsccreen - activeWin?.get_compositor_private() - .set_pivot_point(0.5, 1); - activeWin.get_compositor_private().scale_y = - 1.0 + (progress * 0.025); - } - else if (ui >= 5) { - // un-fullsccreen / restore - activeWin?.get_compositor_private() - .set_pivot_point(0.5, 1); - if (ui == 6) { - activeWin.get_compositor_private().scale_y = - activeWin.get_compositor_private().scale_x = - 1.0 - (progress * 0.04); - } - else { - activeWin.get_compositor_private().scale_y = - 1.0 - (progress * 0.025); - } - } - else if (ui <= 3) { - if (!this._actionWidgets[wid]) { - if (this._actionWidgets.tilerHider) { - clearTimeout(this._actionWidgets.tilerHider); - this._actionWidgets.tilerHider = null; - } - let moarea = activeWin - .get_work_area_current_monitor(); - if (ui == 1) { - // max - this._showPreview( - moarea.x, - moarea.y, - moarea.width, - moarea.height - ); - } - else if (ui == 2) { - // snap left - this._showPreview( - moarea.x, - moarea.y, - moarea.width / 2, - moarea.height - ); - } - else if (ui == 3) { - // snap right - this._showPreview( - moarea.x - + (moarea.width / 2), - moarea.y, - moarea.width / 2, - moarea.height - ); - } - this._actionWidgets[wid] = 1; - } - } - } - else { - if (ui <= 3) { - // max, snap - if (this._actionWidgets.tilerHider) { - clearTimeout(this._actionWidgets.tilerHider); - this._actionWidgets.tilerHider = null; - } - if (this._actionWidgets[wid] && (progress > 0)) { - if (ui == 1) { - activeWin.maximize(Meta.MaximizeFlags.BOTH); - } - else if (ui == 2) { - this._setSnapWindow(0); - } - else if (ui == 3) { - this._setSnapWindow(1); - } - } - this._actionWidgets.tilerHider = setTimeout( - function (me) { - me._hidePreview(); - me._actionWidgets.tilerHider = null; - }, 100, this); - this._actionWidgets[wid] = 0; - } - else { - // resize back - activeWin?.get_compositor_private().ease({ - duration: Math.round(200 * progress), - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - scale_y: 1, - scale_x: 1, - onStopped: () => { - activeWin?.get_compositor_private() - .set_pivot_point(0, 0); - } - }); - if (progress >= 0.5) { - if (ui == 4) { - // fullscreen - activeWin.make_fullscreen(); - } - else if (ui == 5) { - // un-fullscreen - activeWin.unmake_fullscreen(); - } - else if (ui == 6) { - // restore - activeWin.unmaximize( - Meta.MaximizeFlags.BOTH - ); - if (activeWin.isTiled) { - this._sendKeyPress([ - Clutter.KEY_Super_L, Clutter.KEY_Down - ]); - } - } - } - } - } - } - } - // - // End Of Actions - // - } -} - -// Export Extension -export default class WindowGesturesExtension extends Extension { - // Enable Extension - enable() { - this.manager = new Manager(this); - } - - // Disable Extension - disable() { - this.manager.destroy(); - this.manager = null; - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/metadata.json b/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/metadata.json deleted file mode 100644 index 8869ed2b..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Manage window with touchpad gestures", - "name": "Window Gestures", - "settings-schema": "org.gnome.shell.extensions.windowgestures", - "shell-version": [ - "45", - "46" - ], - "url": "https://github.com/amarullz/windowgestures", - "uuid": "windowgestures@extension.amarullz.com", - "version": 7 -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/prefs.js b/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/prefs.js deleted file mode 100644 index 831f85d0..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/prefs.js +++ /dev/null @@ -1,306 +0,0 @@ -/* prefs.js - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -import Adw from 'gi://Adw'; -import Gtk from 'gi://Gtk'; -import Gio from 'gi://Gio'; -import Gdk from 'gi://Gdk'; -import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; - -export default class extends ExtensionPreferences { - fillPreferencesWindow(window) { - const WEBSITE_LINK = "https://amarullz.com/"; - const PAYPAL_LINK = "https://paypal.me/amarullz"; - const GNU_SOFTWARE = '' + - 'This program comes with absolutely no warranty.\n' + - 'See the ' + - 'GNU General Public License, version 2 or later for details.' + - ''; - let isSwap = this.getSettings().get_boolean('three-finger'); - - // Gesture Settings - const gestures = new Adw.PreferencesGroup({ title: "Gestures" }); - this._createSwitch( - gestures, "three-finger", - "Switch 3 and 4 fingers", - "" - ); - this._createSwitch( - gestures, "use-active-window", - "Use active window", - "If true, gesture will control active window rather than window on current pointer. This will disable resize function" - ); - this._createSwitch( - gestures, "taphold-move", - "Tap and hold to move/resize window", - "Trigger move window by tap and hold rather than by swipe down" - ); - - - // Function Settings - const fn = new Adw.PreferencesGroup({ title: "Active Functions" }); - this._createSwitch( - fn, "pinch-enable", - "Enable pinch gestures", - "" - ); - this._createSwitch( - fn, "fn-resize", - "Enable resize window", - "" - ); - this._createSwitch( - fn, "fn-move", - "Enable move window", - "" - ); - this._createSwitch( - fn, "fn-fullscreen", - "Enable fullscreen", - "" - ); - this._createSwitch( - fn, "fn-maximized-snap", - "Enable maximized window snap", - "" - ); - this._createSwitch( - fn, "fn-move-snap", - "Enable move window snap", - "" - ); - - // Pinch Settings - const action_list = [ - "Disable", - "Minimize window", // 1 - "Close window", // 2 - "Show desktop", // 3 - - "Next window", // 4 - "Previous window", // 5 - - "Send window left", // 6 - "Send window right", // 7 - - "Back", // 8 - "Forward", // 9 - "Brightness up", // 10 - "Brightness down", // 11 - "Volume up", // 12 - "Volume down", // 13 - "Mute", // 14 - "Media play", // 15 - "Media next", // 16 - "Media previous", // 17 - - "Alt+Tab switch", // 18 - "Overview", // 19 - "Application Grid", // 20 - "Quick settings", // 21 - "Notification", // 22 - "Run (Alt+F2)", // 23 - - ]; - - const act1 = new Adw.PreferencesGroup({ - title: (isSwap ? "3" : "4") + " Fingers Actions" - }); - this._createCombo(act1, "swipe4-left", - "Swipe left", "", action_list); - this._createCombo(act1, "swipe4-right", - "Swipe right", "", action_list); - this._createCombo(act1, "swipe4-updown", - "Swipe down", - "Swipe up > down if Tap and hold to move/resize window disabled", - action_list); - - const act2 = new Adw.PreferencesGroup({ - title: (isSwap ? "4" : "3") + " Fingers Actions" - }); - this._createCombo(act2, "swipe3-down", - "Swipe down", "", action_list); - this._createCombo(act2, "swipe3-left", - "Swipe down > left", "", action_list); - this._createCombo(act2, "swipe3-right", - "Swipe down > right", "", action_list); - this._createCombo(act2, "swipe3-downup", - "Swipe down > up", "", action_list); - - const act3 = new Adw.PreferencesGroup({ title: "Pinch Actions" }); - this._createCombo(act3, "pinch3-in", - "Pinch-in 3 fingers", "", action_list); - this._createCombo(act3, "pinch3-out", - "Pinch-out 3 fingers", "", action_list); - this._createCombo(act3, "pinch4-in", - "Pinch-in 4 fingers", "", action_list); - this._createCombo(act3, "pinch4-out", - "Pinch-out 4 fingers", "", action_list); - - - // Function Settings - const ui = new Adw.PreferencesGroup({ title: "User Interface" }); - this._createCombo(ui, "ui-theme", - "UI color scheme", "", [ - "Follow system", "Light", "Dark" - ]); - this._createCombo(ui, "winswitch-position", - "Window switch ui position", "", [ - "Top", "Center", "Bottom" - ]); - - - // Tweaks Settings - const tweaks = new Adw.PreferencesGroup({ title: "Tweaks" }); - this._createSpin(tweaks, "edge-size", - "Resize edge size", - "Number of pixel from window egdes to determine resize action", - 16, 96, 4); - this._createSpin(tweaks, "top-edge-size", - "Title edge size", - "Number of pixel from top of window to determine move action", - 16, 96, 4); - this._createSpin(tweaks, "gesture-threshold", - "Gesture threshold", - "", - 16, 64, 4); - this._createSpin(tweaks, "gesture-cancel-threshold", - "Gesture cancel threshold", - "", - 4, 32, 1); - this._createSpin(tweaks, "gesture-acceleration", - "Gesture acceleration", - "", - 10, 25, 1); - this._createSpin(tweaks, "pinch-in-scale", - "Pinch in scale target", - "", - 30, 80, 5); - this._createSpin(tweaks, "pinch-out-scale", - "Pinch out scale target", - "", - 120, 200, 5); - - - // About - const about = new Adw.PreferencesGroup({ title: "About" }); - const aboutVersion = new Adw.ActionRow({ - title: 'Window Gestures Version', - }); - aboutVersion.add_suffix(new Gtk.Label({ - label: this.metadata.version.toString(), - css_classes: ['dim-label'], - })); - about.add(aboutVersion); - const githubRow = this._createLinkRow(window, 'Source Github', this.metadata.url); - about.add(githubRow); - const websiteRow = this._createLinkRow(window, 'Visit Website', WEBSITE_LINK); - about.add(websiteRow); - const donateRow = this._createLinkRow(window, 'Donate via PayPal', PAYPAL_LINK); - about.add(donateRow); - - // GNU - const gnuSoftwareGroup = new Adw.PreferencesGroup(); - const gnuSofwareLabel = new Gtk.Label({ - label: GNU_SOFTWARE, - use_markup: true, - justify: Gtk.Justification.CENTER, - }); - const gnuSofwareLabelBox = new Gtk.Box({ - orientation: Gtk.Orientation.VERTICAL, - valign: Gtk.Align.END, - vexpand: true, - }); - gnuSofwareLabelBox.append(gnuSofwareLabel); - gnuSoftwareGroup.add(gnuSofwareLabelBox); - - const page = new Adw.PreferencesPage(); - page.add(gestures); - page.add(act1); - page.add(act2); - page.add(act3); - page.add(fn); - page.add(ui); - page.add(tweaks); - page.add(about); - page.add(gnuSoftwareGroup); - window.add(page); - } - - /* Create Switch Config */ - _createSwitch(parent, bind, title, subtitle) { - const el = new Adw.SwitchRow({ - title: title, - subtitle: subtitle - }); - parent.add(el); - this.getSettings().bind( - bind, el, 'active', Gio.SettingsBindFlags.DEFAULT); - } - - /* Create Switch Config */ - _createSpin(parent, bind, title, subtitle, min, max, inc) { - const el = new Adw.SpinRow({ - title: title, - subtitle: subtitle, - adjustment: new Gtk.Adjustment({ - lower: min, - upper: max, - step_increment: inc - }) - }); - parent.add(el); - this.getSettings().bind( - bind, el, 'value', Gio.SettingsBindFlags.DEFAULT); - } - - /* Create Combo Row */ - _createCombo(parent, bind, title, subtitle, items) { - const itemStr = new Gtk.StringList(); - for (var i = 0; i < items.length; i++) { - itemStr.append(items[i]); - } - const comboRow = new Adw.ComboRow({ - title: title, - subtitle: subtitle, - model: itemStr, - selected: this.getSettings().get_int(bind), - }); - comboRow.connect('notify::selected', widget => { - this.getSettings().set_int(bind, widget.selected); - }); - parent.add(comboRow); - } - - /* Create Link */ - _createLinkRow(window, title_row, uri) { - const image = new Gtk.Image({ - icon_name: 'adw-external-link-symbolic', - valign: Gtk.Align.CENTER, - }); - const linkRow = new Adw.ActionRow({ - title: title_row, - activatable: true, - }); - linkRow.connect('activated', () => { - Gtk.show_uri(window, uri, Gdk.CURRENT_TIME); - }); - linkRow.add_suffix(image); - return linkRow; - } -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/schemas/gschemas.compiled b/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/schemas/gschemas.compiled deleted file mode 100644 index 293372ab..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/schemas/gschemas.compiled and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/schemas/org.gnome.shell.extensions.windowgestures.gschema.xml b/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/schemas/org.gnome.shell.extensions.windowgestures.gschema.xml deleted file mode 100644 index fb97c3c6..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/schemas/org.gnome.shell.extensions.windowgestures.gschema.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - false - Use 3 Fingers - - - true - Handle Active Window - - - true - Tap and hold to move - - - - true - Enable Resize - - - true - Enable Move - - - true - Enable Maximized Snap - - - true - Enable Move Snap - - - true - Enable Fullscreen - - - true - Enable Pinch - - - - - 0 - Window Switch Indicator Position - - - - 2 - Window Switch Indicator Position - - - - - 7 - Swipe 4 Fingers Left - - - - 6 - Swipe 4 Fingers Right - - - - 3 - Swipe 3 Fingers Down - - - - 5 - Swipe 3 Fingers Left - - - - 4 - Swipe 3 Fingers Right - - - - 0 - Swipe 4 Fingers Up+Down - - - - 0 - Swipe 3 Fingers Down+Up - - - - - - 1 - Pinch-In 3 Fingers - - - - 3 - Pinch-Out 3 Fingers - - - - 0 - Pinch-In 4 Fingers - - - - 0 - Pinch-Out 4 Fingers - - - - - 50 - Pinch-In Scale - - - - 150 - Pinch-In Scale - - - - 32 - Edge Size for Resize - - - - 64 - Title Edge size - - - - 32 - Gesture Threshold - - - - 8 - Gesture Cancel Threshold - - - - - 15 - Gesture Acceleration - - - - \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/stylesheet.css b/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/stylesheet.css deleted file mode 100644 index 95409aad..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/extensions/windowgestures@extension.amarullz.com/stylesheet.css +++ /dev/null @@ -1,96 +0,0 @@ -/* stylesheet.css - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -/* .wgs-dark = dark mode */ - -/* Window Switching Indicator */ -.wgs-winswitch { - text-align: center; - border-radius: 48px; -} - -.wgs-winswitch .wgs-winswitch-ico { - padding: 5px; - border-radius: 5px; - background-color: rgba(120, 120, 120, 0); - transition-property: background-color; - transition-duration: 0.3s; -} - -.wgs-winswitch .wgs-winswitch-ico.selected { - background-color: rgba(120, 120, 120, 0.6); -} - -/* Key Indicator */ -.wgs-indicator-keys { - width: 128px; - height: 128px; - border-radius: 64px; - text-align: center; -} - -.wgs-indicator-keys .wgs-widget-icon { - icon-size: 64px; - width: 64px; - height: 64px; - margin: 32px; - color: #000; -} - -/* Back & Forward */ -.wgs-indicator-backforward { - width: 64px; - height: 64px; - border-radius: 32px; - border: 1px solid; -} - -.wgs-indicator-backforward .wgs-widget-icon { - icon-size: 32px; - width: 32px; - height: 32px; - margin: 16px; -} - -/* Light Mode */ -.wgs-winswitch, -.wgs-indicator-keys, -.wgs-indicator-backforward { - background-color: rgba(230, 230, 230, 0.8); - border: 1px solid rgba(240, 240, 240, 0.85); - box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2); -} - -.wgs-indicator-backforward .wgs-widget-icon, -.wgs-indicator-keys .wgs-widget-icon { - color: #000; -} - - -/* Dark Mode */ -.wgs-dark.wgs-winswitch, -.wgs-dark.wgs-indicator-keys, -.wgs-dark.wgs-indicator-backforward { - background-color: rgba(40, 40, 40, 0.8); - border-color: rgba(50, 50, 50, 0.85); -} - -.wgs-dark.wgs-indicator-backforward .wgs-widget-icon, -.wgs-dark.wgs-indicator-keys .wgs-widget-icon { - color: #fff; -} \ No newline at end of file diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/Abel-Regular.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/Abel-Regular.ttf deleted file mode 100644 index 52455016..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/Abel-Regular.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/BebasNeue-Regular.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/BebasNeue-Regular.ttf deleted file mode 100644 index 76e22b8b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/BebasNeue-Regular.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Bold.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Bold.ttf deleted file mode 100644 index 09bf2e75..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Bold.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Light.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Light.ttf deleted file mode 100644 index f6075d24..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Light.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Medium.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Medium.ttf deleted file mode 100644 index b348dfd1..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Medium.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Regular.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Regular.ttf deleted file mode 100644 index ab3c2ba9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Regular.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Retina.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Retina.ttf deleted file mode 100644 index 77b997ae..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-Retina.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-SemiBold.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-SemiBold.ttf deleted file mode 100644 index 93720c5d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/FiraCodeNerdFontMono-SemiBold.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/Material.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/Material.ttf deleted file mode 100755 index be66835d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/Material.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Bold Italic.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Bold Italic.ttf deleted file mode 100644 index 9548f2ba..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Bold Italic.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Bold.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Bold.ttf deleted file mode 100644 index e0e39544..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Bold.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Italic.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Italic.ttf deleted file mode 100644 index 95c2cada..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Italic.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Regular.ttf b/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Regular.ttf deleted file mode 100644 index 88b81490..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/MesloLGS NF Regular.ttf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Black.otf b/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Black.otf deleted file mode 100755 index f50c8d1c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Black.otf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Bold.otf b/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Bold.otf deleted file mode 100755 index ee79a7fb..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Bold.otf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Heavy.otf b/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Heavy.otf deleted file mode 100755 index ec4b34e3..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Heavy.otf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Light.otf b/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Light.otf deleted file mode 100755 index df7d0f70..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Light.otf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Medium.otf b/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Medium.otf deleted file mode 100755 index 4fd89368..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Medium.otf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Regular.otf b/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Regular.otf deleted file mode 100755 index 120603c6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/fonts/SF-Pro-Display-Regular.otf and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/animation.png b/gui/gnome/autocustom-gnome-macos/res/macOS/animation.png deleted file mode 100644 index 40389dc6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/animation.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/background.png b/gui/gnome/autocustom-gnome-macos/res/macOS/background.png deleted file mode 100644 index e8677c9a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/background.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/box.png b/gui/gnome/autocustom-gnome-macos/res/macOS/box.png deleted file mode 100644 index 54876e68..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/box.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/bullet.png b/gui/gnome/autocustom-gnome-macos/res/macOS/bullet.png deleted file mode 100644 index efc80da0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/bullet.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/entry.png b/gui/gnome/autocustom-gnome-macos/res/macOS/entry.png deleted file mode 100644 index a9f4157b..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/entry.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/install-macOS b/gui/gnome/autocustom-gnome-macos/res/macOS/install-macOS deleted file mode 100644 index 531f7c40..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/macOS/install-macOS +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -#Note: No guarantee that this theme will be seen correctly at all screen resolutions available -#execute only from within the macOS folder! - -sudo mkdir /usr/share/plymouth/themes/macOS -clear -sudo rsync -aq --exclude=install-macOS * /usr/share/plymouth/themes/macOS/ -clear -sudo update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth /usr/share/plymouth/themes/macOS/macOS.plymouth 100 -sudo update-alternatives --config default.plymouth #here, choose the number of the theme you want to use then hit enter -sudo update-initramfs -u -echo -echo Installing plymouth-x11... Redundant if already installed. -sudo apt-get install plymouth-x11 -echo -echo Running 10-second test... -sudo plymouthd ; sudo plymouth --show-splash ; for ((I=0; I<10; I++)); do sleep 1 ; sudo plymouth --update=test$I ; done ; sudo plymouth --quit -exit diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/lock.png b/gui/gnome/autocustom-gnome-macos/res/macOS/lock.png deleted file mode 100644 index a0f8c12f..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/lock.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/logo.png b/gui/gnome/autocustom-gnome-macos/res/macOS/logo.png deleted file mode 100644 index 7d3d510d..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/logo.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/macOS.plymouth b/gui/gnome/autocustom-gnome-macos/res/macOS/macOS.plymouth deleted file mode 100644 index 8c547c3e..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/macOS/macOS.plymouth +++ /dev/null @@ -1,8 +0,0 @@ -[Plymouth Theme] -Name=macOS Sonoma -Description=A Plymouth of MacOS Sonoma -ModuleName=script - -[script] -ImageDir=/usr/share/plymouth/themes/macOS -ScriptFile=/usr/share/plymouth/themes/macOS/macOS.script diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/macOS.script b/gui/gnome/autocustom-gnome-macos/res/macOS/macOS.script deleted file mode 100644 index 68a89209..00000000 --- a/gui/gnome/autocustom-gnome-macos/res/macOS/macOS.script +++ /dev/null @@ -1,246 +0,0 @@ -#By Lozano Juan Pablo - -Window.GetMaxWidth = fun (){ - i = 0; - width = 0; - while (Window.GetWidth(i)){ - width = Math.Max(width, Window.GetWidth(i)); - i++; - } - return width; -}; - -Window.GetMaxHeight = fun (){ - i = 0; - height = 0; - while (Window.GetHeight(i)){ - height = Math.Max(height, Window.GetHeight(i)); - i++; - } - return height; -}; - -anim.imagecount = 32; -anim.target_width = 0.2* 0.46 * Window.GetWidth(); -anim.target_height = 0.2* 0.46 * Window.GetWidth(); - -fun RotatedImage (index){ - index = Math.Int(index); - if (!RotatedImageCache[index]) - RotatedImageCache[index] = anim.original_image.Rotate((Math.Pi*2*index)/anim.imagecount).Scale(anim.target_width, anim.target_height); - - return RotatedImageCache[index]; - } - - -if (Plymouth.GetMode() == "suspend" || Plymouth.GetMode() == "resume") { - background.original_image = ImageNew("suspend.png"); - Window.SetBackgroundTopColor(1, 0, 0); - Window.SetBackgroundBottomColor(0, 1, 0); -} -else { - logo.original_image = ImageNew("logo.png"); - background.original_image = ImageNew("background.png"); - Window.SetBackgroundTopColor(0.180, 0.545, 0.020); - Window.SetBackgroundBottomColor(0.439, 0.573, 0.333); - - anim.image= ImageNew("animation.png"); - anim.original_image= anim.image.Scale(anim.target_width, anim.target_width); - - anim.sprite = SpriteNew(); - anim.sprite.SetImage(RotatedImage (0)); - anim.sprite.SetX((Window.GetX() + Window.GetWidth() - RotatedImage(0).GetWidth()) / 2); - anim.sprite.SetY(Window.GetY() + Window.GetHeight() * 0.37); - anim.angle = 0; - anim.index = 0; - - -} - -ratio = logo.original_image.GetWidth() / logo.original_image.GetHeight(); -reduction = 0.4; -logo.image = logo.original_image.Scale(reduction * Window.GetMaxWidth() , reduction / ratio * Window.GetMaxWidth()); -logo.sprite = SpriteNew(); -logo.sprite.SetImage(logo.image); -logo.opacity_angle = 0; -logo.sprite.SetX((Window.GetX() + Window.GetMaxWidth() - logo.image.GetWidth()) / 2); -logo.sprite.SetY(Window.GetY() + Window.GetHeight() * 0.37); - -background.image = background.original_image.Scale(Window.GetMaxWidth() , Window.GetMaxHeight()); -background.sprite = SpriteNew(); -background.sprite.SetImage(background.image); -background.sprite.SetPosition(Window.GetX(), Window.GetY(), -10); - -sprite_prompt = SpriteNew(); - -fun refresh_callback () - { - if (status == "normal") - { - anim.index += 1; - anim.index %= anim.imagecount; - anim.sprite.SetImage(RotatedImage (anim.index)); - #anim.sprite.SetOpacity (1); - #motif.sprite.SetOpacity(motif.opacity); - } - else - { - anim.sprite.SetOpacity(0); - motif.sprite.SetOpacity(0); - } - - } - -if (Plymouth.GetMode() != "suspend" && Plymouth.GetMode() != "resume") { - Plymouth.SetRefreshFunction (refresh_callback); -} - -#----------------------------------------- Dialog -------------------------------- - -status = "normal"; - -fun dialog_setup() - { - local.box; - local.lock; - local.entry; - local.prompt_sprite; - - box.image = ImageNew("box.png"); - lock.image = ImageNew("lock.png"); - entry.image = ImageNew("entry.png"); - - box.sprite = SpriteNew(); - box.sprite.SetImage(box.image); - box.x = Window.GetX() + Window.GetWidth() / 2 - box.image.GetWidth()/2; - box.y = Window.GetY() + Window.GetHeight() / 2 - box.image.GetHeight()/2; - box.z = 10000; - box.sprite.SetPosition(box.x, box.y, box.z); - - lock.sprite = SpriteNew(); - lock.sprite.SetImage(lock.image); - lock.x = box.x + box.image.GetWidth()/2 - (lock.image.GetWidth() + entry.image.GetWidth()) / 2; - lock.y = box.y + box.image.GetHeight()/2 - lock.image.GetHeight()/2; - lock.z = box.z + 1; - lock.sprite.SetPosition(lock.x, lock.y, lock.z); - - entry.sprite = SpriteNew(); - entry.sprite.SetImage(entry.image); - entry.x = lock.x + lock.image.GetWidth(); - entry.y = box.y + box.image.GetHeight()/2 - entry.image.GetHeight()/2; - entry.z = box.z + 1; - entry.sprite.SetPosition(entry.x, entry.y, entry.z); - - prompt_sprite = SpriteNew(); - prompt_sprite.SetPosition(box.x, box.y - 20, box.z); - - global.dialog.box = box; - global.dialog.lock = lock; - global.dialog.entry = entry; - global.dialog.bullet_image = ImageNew("bullet.png"); - global.dialog.prompt_sprite = prompt_sprite; - dialog_opacity (1); - } - -fun dialog_opacity(opacity) - { - dialog.box.sprite.SetOpacity(opacity); - dialog.lock.sprite.SetOpacity(opacity); - dialog.entry.sprite.SetOpacity(opacity); - dialog.prompt_sprite.SetOpacity(opacity); - for (index = 0; dialog.bullet[index]; index++) - { - dialog.bullet[index].sprite.SetOpacity(opacity); - } - } - -fun display_normal_callback () - { - global.status = "normal"; - if (global.dialog) - dialog_opacity (0); - } - -fun display_password_callback (prompt, bullets) - { - global.status = "password"; - if (!global.dialog) - dialog_setup(); - else - dialog_opacity(1); - motif.sprite.SetOpacity(0); - anim.sprite.SetOpacity(0); - - dialog.prompt_sprite.SetImage(Image.Text(prompt, 1.0, 1.0, 1.0)); - for (index = 0; dialog.bullet[index] || index < bullets; index++) - { - - if (!dialog.bullet[index]) - { - dialog.bullet[index].sprite = SpriteNew(); - dialog.bullet[index].sprite.SetImage(dialog.bullet_image); - dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_image.GetWidth(); - dialog.bullet[index].y = dialog.entry.y + dialog.entry.image.GetHeight() / 2 - dialog.bullet_image.GetHeight() / 2; - dialog.bullet[index].z = dialog.entry.z + 1; - dialog.bullet[index].sprite.SetPosition(dialog.bullet[index].x, dialog.bullet[index].y, dialog.bullet[index].z); - } - if (index < bullets) - dialog.bullet[index].sprite.SetOpacity(1); - else - dialog.bullet[index].sprite.SetOpacity(0); - } - } - -fun display_message_callback (prompt) - { - -prompt = Image.Text(prompt,1.0, 1.0, 1.0); -sprite_prompt.SetImage(prompt); -sprite_prompt.SetPosition(Window.GetX() + (Window.GetWidth() - prompt.GetWidth()) / 2, Window.GetY() + Window.GetHeight() * 0.93, 2); - } - -/* instantiate dialog at startup, to ensure all icons are loaded in memory before initrd is unmounted, in case /usr isn't mounted yet */ -dialog_setup(); dialog_opacity(0); -Plymouth.SetDisplayNormalFunction(display_normal_callback); -Plymouth.SetDisplayPasswordFunction(display_password_callback); -Plymouth.SetMessageFunction(display_message_callback); - -#----------------------------------------- Progress Bar -------------------------------- - -progress_box.image = Image("progress_box.png"); -progress_box.sprite = Sprite(progress_box.image); - -progress_box.x = Window.GetX() + Window.GetWidth() / 2 - progress_box.image.GetWidth() / 2; -progress_box.y = Window.GetY() + Window.GetHeight() * 0.65 - progress_box.image.GetHeight() / 2; -progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 0); - -progress_bar.original_image = Image("progress_bar.png"); -progress_bar.sprite = Sprite(); - -progress_bar.x = Window.GetX() + Window.GetWidth() / 2 - progress_bar.original_image.GetWidth() / 2; -progress_bar.y = Window.GetY() + Window.GetHeight() * 0.65 - progress_box.image.GetHeight() / 2 + (progress_box.image.GetHeight() - progress_bar.original_image.GetHeight()) / 2; -progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 1); - -fun progress_callback (duration, progress) - { - if (progress_bar.image.GetWidth () != Math.Int (progress_bar.original_image.GetWidth () * progress)) - { - progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress, progress_bar.original_image.GetHeight()); - progress_bar.sprite.SetImage (progress_bar.image); - } - } - -Plymouth.SetBootProgressFunction(progress_callback); - -#----------------------------------------- Quit -------------------------------- - -fun quit_callback () -{ - anim.sprite.SetOpacity (0); - if (Plymouth.GetMode() == "shutdown") { - motif.sprite.SetOpacity(0); - } -} - -Plymouth.SetQuitFunction(quit_callback); - diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/motif.png b/gui/gnome/autocustom-gnome-macos/res/macOS/motif.png deleted file mode 100644 index 4cc6b45a..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/motif.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_bar.png b/gui/gnome/autocustom-gnome-macos/res/macOS/progress_bar.png deleted file mode 100644 index 46186fe5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_bar.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box.png b/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box.png deleted file mode 100644 index 8e9cb85c..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box_background.png b/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box_background.png deleted file mode 100644 index 7e2818c0..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box_background.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box_edge.png b/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box_edge.png deleted file mode 100644 index 3de7cd57..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/progress_box_edge.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macOS/suspend.png b/gui/gnome/autocustom-gnome-macos/res/macOS/suspend.png deleted file mode 100644 index 56274828..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macOS/suspend.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/MacRancho-Dark.png b/gui/gnome/autocustom-gnome-macos/res/macosw/MacRancho-Dark.png deleted file mode 100644 index a4a614d5..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/MacRancho-Dark.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/MacRancho-Light.png b/gui/gnome/autocustom-gnome-macos/res/macosw/MacRancho-Light.png deleted file mode 100644 index 9fb55805..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/MacRancho-Light.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/MacSonoma-Dark.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/MacSonoma-Dark.jpg deleted file mode 100644 index a64b9b19..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/MacSonoma-Dark.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/MacSonoma-Light.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/MacSonoma-Light.jpg deleted file mode 100644 index 97378290..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/MacSonoma-Light.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/MacVentura-Dark.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/MacVentura-Dark.jpg deleted file mode 100644 index 22a57bb6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/MacVentura-Dark.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/MacVentura-Light.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/MacVentura-Light.jpg deleted file mode 100644 index eb036d07..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/MacVentura-Light.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-dark.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-dark.jpg deleted file mode 100644 index 38551df7..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-dark.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-light.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-light.jpg deleted file mode 100644 index da8758aa..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-light.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-morning.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-morning.jpg deleted file mode 100644 index 81f57ad6..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey-morning.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey.jpg b/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey.jpg deleted file mode 100644 index 62979cd9..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/Monterey.jpg and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/WhiteSur-dark.png b/gui/gnome/autocustom-gnome-macos/res/macosw/WhiteSur-dark.png deleted file mode 100644 index 01ab9260..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/WhiteSur-dark.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/res/macosw/WhiteSur-light.png b/gui/gnome/autocustom-gnome-macos/res/macosw/WhiteSur-light.png deleted file mode 100644 index 3ad52baf..00000000 Binary files a/gui/gnome/autocustom-gnome-macos/res/macosw/WhiteSur-light.png and /dev/null differ diff --git a/gui/gnome/autocustom-gnome-macos/uninstall_fedora40.sh b/gui/gnome/autocustom-gnome-macos/uninstall_fedora40.sh deleted file mode 100755 index 9d1a88c6..00000000 --- a/gui/gnome/autocustom-gnome-macos/uninstall_fedora40.sh +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/bash -# -# Script Name: uninstall_fedora.sh -# Version : 1.0 -# Description: Uninstallation script to revert customizations -# GNOME 46 Look Like macOS on Fedora 40 -# -# For Linux : Fedora 40 -# For Desktop Environment : GNOME Shell 46 -# Author: linuxscoop -# Youtube: https://youtube.com/user/linuxscoop -# Created: May 25, 2024 -# Last Modified: June 07, 2024 -# -# -# # Remove installed GNOME apps and dependencies -# remove_gnome_apps() { -# clear -# echo "Removing GNOME apps and dependencies..." -# sudo dnf remove -y gnome-weather \ -# gnome-maps \ -# gnome-audio \ -# gnome-calendar \ -# gnome-clocks \ -# gnome-connections \ -# gnome-console \ -# gnome-contacts \ -# gnome-music \ -# vlc \ -# gnome-shell-extension-pomodoro -# } - -## Uninstall WhiteSur GTK theme -uninstall_whitesur_gtk_theme() { - rm -rf $HOME/.themes/WhiteSur* - rm -rf $HOME/.config/gtk-4.0/gtk.css -} - -# Uninstall WhiteSur icon theme -uninstall_whitesur_icon_theme() { - rm -rf $HOME/.icons/WhiteSur* -} - -# Uninstall WhiteSur Firefox Theme -uninstall_whitesur_firefox_theme() { - cd src/WhiteSur-gtk-theme - ./install.sh -r - cd ../../ -} - -# Remove Cursors theme -remove_cursors_theme() { - rm -rf $HOME/.icons/WhiteSur-cursors -} - -# Remove Fonts and Wallpapers -remove_fonts_and_wallpapers() { - rm -rf $HOME/.local/share/fonts/* - sudo rm -rf /usr/share/backgrounds/macosw -} - -# Remove GNOME Shell Extensions -remove_gnome_shell_extensions() { - rm -rf $HOME/.local/share/gnome-shell/extensions/* -} - -# Remove Cava, Neofetch and their configurations -remove_cava_neofetch() { - clear - echo "Removing Cava, Neofetch and their configurations..." - sudo dnf remove -y cava neofetch - rm -rf "$HOME/.config/cava" - rm -rf "$HOME/.config/neofetch" -} - -# Remove Oh My Zsh and revert to default shell -remove_zsh_oh_my_zsh() { - clear - echo "Removing Oh My Zsh..." - sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/uninstall.sh)" - rm -r $HOME/.p10k.zsh - sudo dnf remove -y zsh - sudo chsh -s "$(which bash)" "$(whoami)" -} - -remove_flatpak_apps() { - clear - echo "Uninstall Flatpak Applications.." - flatpak uninstall --delete-data io.bassi.Amberol - # Clean up any unused libraries - flatpak uninstall --unused - sudo rm -rf /var/lib/flatpak -} - -# # Remove Flatpak applications and disable Flatpak support -# disable_flatpak_and_appimage_support() { -# clear -# echo "Removing Flatpak applications and disabling Flatpak support..." -# flatpak uninstall -y io.bassi.Amberol #com.mattjakeman.ExtensionManager com.github.KRTirtho.Spotube -# sudo dnf remove -y gnome-software gnome-software-plugin-flatpak flatpak fuse -# sudo flatpak remote-delete flathub -# } - -# Remove Plymouth macOS theme -remove_plymouth_macos_theme() { - clear - echo "Removing Plymouth macOS theme..." - sudo plymouth-set-default-theme -R spinner - sudo rm -rf /usr/share/plymouth/themes/macOS -} - -# Restore default GNOME Shell configuration -restore_default_gnome_shell_configuration() { - clear - echo "Restoring default GNOME Shell configuration..." - dconf reset -f / -} - -# Prompt for confirmation to reboot the system and handle user's choice -prompt_for_reboot() { - clear - read -p "Uninstallation completed successfully. It is recommended to reboot your system for changes to take effect. Reboot now? (y/n): " choice - - if [[ "$choice" == "y" || "$choice" == "Y" ]]; then - echo "Rebooting..." - sudo reboot - else - echo "Reboot skipped. Please reboot manually to apply the changes." - fi -} - -# Main function to execute all steps -main() { - remove_gnome_shell_extensions - remove_whitesur_gtk_theme - remove_whitesur_icon_theme - remove_whitesur_firefox_theme - remove_cursors_theme - remove_cava_neofetch - remove_zsh_oh_my_zsh - remove_powerlevel10k_theme - remove_flatpak_apps - remove_plymouth_macos_theme - restore_default_gnome_shell_configuration - remove_fonts_and_wallpapers - prompt_for_reboot -} - -# Execute the main function -main diff --git a/gui/gnome/autocustom-gnome-macos/uninstall_ubuntu2404.sh b/gui/gnome/autocustom-gnome-macos/uninstall_ubuntu2404.sh deleted file mode 100644 index a8a7d2ce..00000000 --- a/gui/gnome/autocustom-gnome-macos/uninstall_ubuntu2404.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/bash -# -# Script Name: uninstall_ubuntu24.04.sh -# Version : 1.0 -# Description: Uninstallation script for reverting the changes made by install_ubuntu24.04.sh -# GNOME 46 Look Like macOS on Ubuntu 24.04 -# -# For Linux : Ubuntu 24.04 -# For Desktop Environment : GNOME Shell 46 -# Author: linuxscoop -# Youtube: https://youtube.com/user/linuxscoop -# Created: May 25, 2024 -# Last Modified: June 07, 2024 -# -# Remove Firefox installed from Mozilla PPA and its configurations -remove_firefox_from_mozilla_ppa() { - sudo apt remove --purge -y firefox - sudo rm /etc/apt/apt.conf.d/51unattended-upgrades-firefox - sudo rm /etc/apt/preferences.d/mozillateamppa - sudo add-apt-repository --remove ppa:mozillateam/ppa -y -} - -# Reinstall snap and common snap apps -reinstall_snap_and_apps() { - clear - echo "Reinstalling snap and common snap apps..." - sudo rm /etc/apt/preferences.d/nosnap.pref - sudo apt update - sudo apt install snapd -y - sudo snap install core22 - sudo snap install firefox - sudo snap install snap-store - sudo snap install gnome-42-2204 - sudo snap install gtk-common-themes - sudo snap install snapd-desktop-integration - sudo snap install firmware-updater -} - -# Uninstall GNOME Apps and Dependencies -uninstall_gnome_apps() { - sudo apt remove --purge -y gnome-weather \ - gnome-maps \ - gnome-audio \ - gnome-calendar \ - gnome-clocks \ - gnome-connections \ - gnome-console \ - gnome-contacts \ - gnome-music \ - vlc \ - gnome-shell-pomodoro -} - -# Uninstall WhiteSur GTK theme -uninstall_whitesur_gtk_theme() { - rm -rf $HOME/.themes/WhiteSur* - rm -rf $HOME/.config/gtk-4.0/*.* -} - -# Uninstall WhiteSur icon theme -uninstall_whitesur_icon_theme() { - rm -rf $HOME/.icons/WhiteSur* -} - -# Uninstall WhiteSur Firefox Theme -uninstall_whitesur_firefox_theme() { - cd src/WhiteSur-gtk-theme - ./install.sh -r - cd ../../ -} - -# Remove Cursors theme -remove_cursors_theme() { - rm -rf $HOME/.icons/WhiteSur-cursors -} - -# Remove Fonts and Wallpapers -remove_fonts_and_wallpapers() { - rm -rf $HOME/.local/share/fonts/* - sudo rm -rf /usr/share/backgrounds/macosw -} - -# Remove GNOME Shell Extensions -remove_gnome_shell_extensions() { - rm -rf $HOME/.local/share/gnome-shell/extensions/* -} - -# Uninstall Cava, Neofetch and their configurations -uninstall_cava_neofetch() { - sudo apt remove --no-install-recommends neofetch cava -y - rm -rf $HOME/.config/cava - rm -rf $HOME//.config/neofetch -} - -# Remove Oh My Zsh and revert to bash -uninstall_zsh_oh_my_zsh() { - sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/uninstall.sh)" - rm -r $HOME/.p10k.zsh - sudo apt remove --no-install-recommends zsh -y - sudo chsh -s /bin/bash "$USER" -} - -remove_flatpak_apps() { - clear - echo "Uninstall Flatpak Applications.." - flatpak uninstall --delete-data io.bassi.Amberol - # Clean up any unused libraries - flatpak uninstall --unused -} - -# Disable Flatpak, Appimage Support and remove Flathub Repository -disable_flatpak_and_appimage_support() { - sudo apt remove --purge -y gnome-software-plugin-flatpak flatpak libfuse2 - sudo rm -rf /var/lib/flatpak -} - -# Uninstall Plymouth macOS theme -uninstall_plymouth_macos_theme() { - sudo rm -rf /usr/share/plymouth/themes/macOS - sudo update-alternatives --remove default.plymouth /usr/share/plymouth/themes/macOS/macOS.plymouth - sudo update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth /usr/share/plymouth/themes/bgrt/bgrt.plymouth 110 - sudo update-alternatives --config default.plymouth - sudo update-initramfs -u -} - -# Restore GNOME Shell Configuration to default -restore_default_gnome_shell_configuration() { - dconf reset -f / -} - -# Clean up -cleanup() { - sudo apt autoremove -y - sudo apt clean -} - -# Execute all uninstallation steps -reinstall_snap_and_apps -remove_firefox_from_mozilla_ppa -uninstall_apps_and_dependencies -uninstall_whitesur_gtk_theme -uninstall_whitesur_icon_theme -uninstall_whitesur_firefox_theme -remove_cursors_theme -remove_gnome_shell_extensions -uninstall_cava_neofetch -uninstall_zsh_oh_my_zsh -uninstall_powerlevel10k_theme -disable_flatpak_and_appimage_support -uninstall_plymouth_macos_theme -remove_fonts_and_wallpapers -restore_default_gnome_shell_configuration -cleanup - -clear - -echo "Uninstallation completed successfully. Please logout and log back in for changes to take effect." -read -p "Do you want to logout now? (y/n): " choice - -if [[ "$choice" == "y" ]]; then - gnome-session-quit --logout - echo "Logging out. Please log back in for changes to take effect." -else - echo "No changes made. You can manually logout and log back in later." -fi \ No newline at end of file