#!/data/data/com.termux/files/usr/bin/bash # # Termux Desktop # A simple script to easily install supported desktop environments and # window managers, along with other essential configurations and tools. # # 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 . # # Author : @sabamdarif # License : GPL-v3 # Description: This script automates the installation of various desktop environments and window managers # Repository : https://github.com/sabamdarif/termux-desktop ######################################################################### # # Call First # ######################################################################### # shellcheck disable=SC2154 R="$(printf '\033[1;31m')" G="$(printf '\033[1;32m')" Y="$(printf '\033[1;33m')" B="$(printf '\033[1;34m')" C="$(printf '\033[1;36m')" NC="$(printf '\033[0m')" BOLD="$(printf '\033[1m')" cd "$HOME" || exit 1 ############### Define basic initial values ###################### TERMUX_DESKTOP_PATH="/data/data/com.termux/files/usr/etc/termux-desktop" CONFIG_FILE="$TERMUX_DESKTOP_PATH/configuration.conf" LOG_FILE="/data/data/com.termux/files/home/termux-desktop.log" CALL_FROM_CHANGE_DISTRO=false CALL_FROM_CHANGE_STYLE=false IS_TERMUX_API_INSTALLED=false LITE_MODE="${LITE,,}" ################################################################## # create detailed log output function debug_msg() { local debug_message="[DEBUG] running: $BASH_COMMAND" echo "$debug_message" echo "$(date '+%Y-%m-%d %H:%M:%S') - $debug_message" >>"$LOG_FILE" } function banner() { clear printf "%s############################################################\n" "$C" printf "%s# #\n" "$C" printf "%s# ▀█▀ █▀▀ █▀█ █▀▄▀█ █ █ ▀▄▀   █▀▄ █▀▀ █▀ █▄▀ ▀█▀ █▀█ █▀█ #\n" "$C" printf "%s# █  ██▄ █▀▄ █ █ █▄█ █ █   █▄▀ ██▄ ▄█ █ █  █  █▄█ █▀▀ #\n" "$C" printf "%s# #\n" "$C" printf "%s######################### Termux Gui #######################%s\n" "$C" "$NC" echo " " } # check if the script is running on termux or not function check_termux() { if [[ -z "$PREFIX" && "$PREFIX" != *"/com.termux/"* ]]; then echo "${R}[${R}☓${R}]${R}${BOLD}Please run it inside termux${NC}" exit 1 fi } ######################################################################### # # Base Functions # ######################################################################### function print_log() { local timestamp timestamp="$(date '+%Y-%m-%d %H:%M:%S')" local log_level="${2:-INFO}" # Default log level is INFO if not specified local message="$1" echo "[${timestamp}] ${log_level}: ${message}" >>"$LOG_FILE" } function log_warn() { local timestamp timestamp=$(date '+%Y-%m-%d %H:%M:%S') local message="$1" echo "[${timestamp}] WARN: ${message}" >>"$LOG_FILE" } function log_error() { local timestamp timestamp=$(date '+%Y-%m-%d %H:%M:%S') local message="$1" echo "[${timestamp}] ERROR: ${message}" >>"$LOG_FILE" } function log_debug() { local timestamp timestamp=$(date '+%Y-%m-%d %H:%M:%S') local message="$1" echo "[${timestamp}] DEBUG: ${message}" >>"$LOG_FILE" } function print_success() { local msg msg="$1" echo "${R}[${G}✓${R}]${G} $msg ${NC}" log_debug "$msg" } function print_failed() { local msg msg="$1" echo "${R}[${R}☓${R}]${R} $msg ${NC}" log_debug "$msg" } function print_warn() { local msg msg="$1" echo "${R}[${Y}!${R}]${Y} $msg ${NC}" log_debug "$msg" } function print_msg() { local msg msg="$1" echo "${R}[${C}-${R}]${G} $msg ${NC}" log_debug "$msg" } function wait_for_keypress() { read -n1 -s -r -p "${R}[${C}-${R}]${G} Press any key to continue, CTRL+c to cancel...${NC}" echo } function check_and_create_directory() { if [[ -n "$1" && ! -d "$1" ]]; then mkdir -p "$1" log_debug "$1" fi } # first check then delete function check_and_delete() { local files_folders for files_folders in "$@"; do if [[ -e "$files_folders" ]]; then rm -rf "$files_folders" >/dev/null 2>&1 log_debug "$files_folders" fi done } # first check then backup function check_and_backup() { log_debug "Starting backup for: $*" # shellcheck disable=SC2206 local files_folders_list=($@) local files_folders local date_str date_str=$(date +"%d-%m-%Y") for files_folders in "${files_folders_list[@]}"; do if [[ -e "$files_folders" ]]; then local backup="${files_folders}-${date_str}.bak" if [[ -e "$backup" ]]; then print_msg "Backup $backup already exists" else print_msg "Backing up $files_folders" mv "$files_folders" "$backup" log_debug "$files_folders $backup" fi else print_msg "Path $files_folders does not exist" fi done } function download_file() { local dest local url local max_retries=5 local attempt=1 local successful_attempt=0 if [[ -z "$2" ]]; then url="$1" dest="$(basename "$url")" else dest="$1" url="$2" fi if [[ -z "$url" ]]; then print_failed "No URL provided!" return 1 fi while [[ $attempt -le $max_retries ]]; do print_msg "Downloading $dest..." if [[ ! -s "$dest" ]]; then check_and_delete "$dest" fi if command -v wget &>/dev/null; then wget --tries=5 --timeout=15 --retry-connrefused -O "$dest" "$url" else curl -# -L "$url" -o "$dest" fi if [[ -f "$dest" && -s "$dest" ]]; then successful_attempt=$attempt break else print_failed "Download failed. Retrying... ($attempt/$max_retries)" fi ((attempt++)) done if [[ -f "$dest" ]]; then if [[ $successful_attempt -eq 1 ]]; then print_success "File downloaded successfully." else print_success "File downloaded successfully on attempt $successful_attempt." fi return 0 fi print_failed "Failed to download the file after $max_retries attempts. Exiting." return 1 } # find a backup file which end with a number pattern and restore it function check_and_restore() { log_debug "Starting restore for: $*" # shellcheck disable=SC2206 local files_folders_list=($@) local files_folders for files_folders in "${files_folders_list[@]}"; do local latest_backup latest_backup=$(find "$(dirname "$files_folders")" -maxdepth 1 -name "$(basename "$files_folders")-[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9].bak" 2>/dev/null | sort | tail -n 1) if [[ -z "$latest_backup" ]]; then print_msg "No backup found for $files_folders" continue fi if [[ -e "$files_folders" ]]; then print_msg "File $files_folders already exists" else print_msg "Restoring $files_folders" mv "$latest_backup" "$files_folders" log_debug "$latest_backup $files_folders" fi done } function detact_package_manager() { # shellcheck disable=SC1091 source "/data/data/com.termux/files/usr/bin/termux-setup-package-manager" if [[ "$TERMUX_APP_PACKAGE_MANAGER" == "apt" ]]; then PACKAGE_MANAGER="apt" elif [[ "$TERMUX_APP_PACKAGE_MANAGER" == "pacman" ]]; then PACKAGE_MANAGER="pacman" else print_failed "${C} Could not detact your package manager, Switching To ${C}pkg ${NC}" fi log_debug "$PACKAGE_MANAGER" } # will check if the package is already installed or not, if it installed then reinstall and print success/failed message function package_install_and_check { log_debug "Starting package installation for: $*" # shellcheck disable=SC2206 packs_list=($@) # pacman part if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then for package_name in "${packs_list[@]}"; do if [[ "$package_name" == *"*"* ]]; then log_debug "Processing wildcard pattern: $package_name" packages=$(pacman -Ssq | grep -E "^${package_name//\*/.*}$") log_debug "matched packages: ${C}$packages" for package in $packages; do retry_count=0 max_retries=5 install_success=false while [[ "$retry_count" -lt "$max_retries" && "$install_success" == false ]]; do retry_count=$((retry_count + 1)) check_and_delete "$PREFIX/var/lib/pacman/db.lck" print_msg "Installing Package : ${C}$package" pacman -S --noconfirm "$package" if pacman -Qi "$package" >/dev/null 2>&1; then print_success "Successfully install package: ${C}$package" install_success=true else print_warn "Failed to install package: ${C}${package}. ${Y}Trying again... ($retry_count)" fi done done else retry_count=0 max_retries=5 install_success=false while [[ "$retry_count" -lt "$max_retries" && "$install_success" == false ]]; do retry_count=$((retry_count + 1)) check_and_delete "$PREFIX/var/lib/pacman/db.lck" print_msg "Installing Package : ${C}$package_name" pacman -S --noconfirm "$package_name" if pacman -Qi "$package_name" >/dev/null 2>&1; then print_success "Successfully install package: ${C}$package_name" install_success=true else print_warn "Failed to install package: ${C}${package_name}. ${Y}Trying again... ($retry_count)" fi done fi done else #apt part for package_name in "${packs_list[@]}"; do if [[ "$package_name" == *"*"* ]]; then log_debug "Processing wildcard pattern: $package_name" packages=$(apt-cache pkgnames | grep -E "^${package_name//\*/.*}$" | sort -u) log_debug "matched packages: $packages" for package in $packages; do retry_count=0 max_retries=5 install_success=false while [[ "$retry_count" -lt "$max_retries" && "$install_success" == false ]]; do retry_count=$((retry_count + 1)) print_msg "Installing package: ${C}$package" apt install "$package" -y if dpkg -s "$package" >/dev/null 2>&1; then print_success "Successfully install package: ${C}$package" install_success=true else print_warn "Failed to install package: ${C}${package}. ${Y}Trying again... ($retry_count)" # Only run recovery commands on failure dpkg --configure -a apt --fix-broken install -y apt install --fix-missing -y fi done done else retry_count=0 max_retries=5 install_success=false while [[ "$retry_count" -lt "$max_retries" && "$install_success" == false ]]; do retry_count=$((retry_count + 1)) print_msg "Installing package: ${C}$package_name" apt install "$package_name" -y if dpkg -s "$package_name" >/dev/null 2>&1; then print_success "Successfully install package: ${C}$package_name" install_success=true else print_warn "Failed to install package: ${C}${package_name}. ${Y}Trying again... ($retry_count)" # Only run recovery commands on failure dpkg --configure -a apt --fix-broken install -y apt install --fix-missing -y fi done fi done fi } # will check the package is installed or not then remove it function package_check_and_remove() { log_debug "Starting package removal for: $*" local packs_list # shellcheck disable=SC2206 packs_list=($@) if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then for package_name in "${packs_list[@]}"; do if [[ "$package_name" == *"*"* ]]; then log_debug "Processing wildcard pattern: $package_name" local packages packages=$(pacman -Qsq | grep -E "^${package_name//\*/.*}$") if [[ -z "$packages" ]]; then print_success "No installed packages found matching: ${C}$package_name" continue fi log_debug "matched packages: $packages" for package in $packages; do local retry_count=0 local max_retries=5 local remove_success=false while [[ "$retry_count" -lt "$max_retries" && "$remove_success" == false ]]; do retry_count=$((retry_count + 1)) check_and_delete "$PREFIX/var/lib/pacman/db.lck" print_msg "Removing Package : ${C}$package" pacman -Rnds --noconfirm "$package" if ! pacman -Qi "$package" >/dev/null 2>&1; then print_success "Successfully removed package: ${C}$package" remove_success=true else print_warn "Failed to remove package: ${C}${package}. ${Y}Trying again...($retry_count)" fi done done else if pacman -Qi "$package_name" >/dev/null 2>&1; then local retry_count=0 local max_retries=5 local remove_success=false while [[ "$retry_count" -lt "$max_retries" && "$remove_success" == false ]]; do retry_count=$((retry_count + 1)) check_and_delete "$PREFIX/var/lib/pacman/db.lck" print_msg "Removing Package : ${C}$package_name" pacman -Rnds --noconfirm "$package_name" if ! pacman -Qi "$package_name" >/dev/null 2>&1; then print_success "Successfully removed package: ${C}$package_name" remove_success=true else print_warn "Failed to remove package: ${C}${package_name}. ${Y}Trying again... ($retry_count)" fi done else print_success "Package ${C}$package_name${G} is not installed.${NC}" fi fi done else for package_name in "${packs_list[@]}"; do if [[ "$package_name" == *"*"* ]]; then log_debug "Processing wildcard pattern: $package_name" local packages packages=$(dpkg-query -W -f='${binary:Package}\n' "${package_name}" 2>/dev/null | grep -v ' ') if [[ -z "$packages" ]]; then print_success "No installed packages found matching: ${C}$package_name" continue fi log_debug "matched packages: $packages" for package in $packages; do local retry_count=0 local max_retries=5 local remove_success=false while [[ "$retry_count" -lt "$max_retries" && "$remove_success" == false ]]; do retry_count=$((retry_count + 1)) print_msg "Removing package: ${C}$package" dpkg --configure -a >/dev/null apt autoremove "$package" -y if ! dpkg -s "$package" >/dev/null 2>&1; then print_success "Successfully removed package: ${C}$package" remove_success=true else print_warn "Failed to remove package: ${C}${package}. ${Y}Trying again...($retry_count)" fi done done else if dpkg -s "$package_name" >/dev/null 2>&1; then local retry_count=0 local max_retries=5 local remove_success=false while [[ "$retry_count" -lt "$max_retries" && "$remove_success" == false ]]; do retry_count=$((retry_count + 1)) print_msg "Removing package: ${C}$package_name" dpkg --configure -a >/dev/null apt autoremove "$package_name" -y if ! dpkg -s "$package_name" >/dev/null 2>&1; then print_success "Successfully removed package: ${C}$package_name" remove_success=true else print_warn "Failed to remove package: ${C}${package_name}. ${Y}Trying again... ($retry_count)" fi done else print_success "Package ${C}$package_name${G} is not installed.${NC}" fi fi done fi } function get_file_name_number() { current_file=$(basename "$0") folder_name="${current_file%.sh}" theme_number=$(echo "$folder_name" | grep -oE '[1-9][0-9]*') log_debug "$theme_number" } function extract_archive() { local archive="$1" if [[ ! -f "$archive" ]]; then print_failed "$archive doesn't exist" fi case "$archive" in *.tar.gz | *.tgz) print_success "Extracting ${C}$archive" tar xzvf "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.tar.xz) print_success "Extracting ${C}$archive" tar xJvf "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.tar.bz2 | *.tbz2) print_success "Extracting ${C}$archive" tar xjvf "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.tar) print_success "Extracting ${C}$archive" tar xvf "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.bz2) print_success "Extracting ${C}$archive" bunzip2 -v "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.gz) print_success "Extracting ${C}$archive${NC}" gunzip -v "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.7z) print_success "Extracting ${C}$archive" 7z x "$archive" -y || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.zip) print_success "Extracting ${C}$archive" unzip "${archive}" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *.rar) print_success "Extracting ${C}$archive" unrar x "$archive" || { print_failed "Failed to extract ${C}$archive" return 1 } ;; *) print_failed "Unsupported archive format: ${C}$archive" return 1 ;; esac print_success "Successfully extracted ${C}$archive" log_debug "$archive" } # download a archive file and extract it in a folder function download_and_extract() { local url="$1" local target_dir="$2" local filename="${url##*/}" if [[ -n "$target_dir" ]]; then check_and_create_directory "$target_dir" cd "$target_dir" || return 1 fi if download_file "$filename" "$url"; then if [[ -f "$filename" ]]; then echo extract_archive "$filename" check_and_delete "$filename" fi else print_failed "Failed to download ${C}${filename}" print_msg "${C}Please check your internet connection" fi log_debug "$url $target_dir $filename" } count_subfolders() { local owner="$1" local repo="$2" local path="$3" local branch="$4" local response response=$(curl -s "https://api.github.com/repos/$owner/$repo/contents/$path?ref=$branch") # Use jq to extract directories and count them; if none found then set to 0 local subfolder_count subfolder_count=$(echo "$response" | jq -r '[.[] | select(.type == "dir")] | length') echo "${subfolder_count:-0}" log_debug "$subfolder_count" } # create a yes / no confirmation prompt function confirmation_y_or_n() { while true; do # prompt read -r -p "${R}[${C}-${R}]${Y}${BOLD} $1 ${Y}(y/n) ${NC}" response # apply default response="${response:-y}" # lowercase response="${response,,}" # reject spaces or slashes if [[ "$response" =~ [[:space:]/] ]]; then echo print_failed "Invalid input: no spaces or slashes allowed. Enter only 'y' or 'n'." echo continue fi # normalize full words to single letters if [[ "$response" =~ ^(yes|y)$ ]]; then response="y" elif [[ "$response" =~ ^(no|n)$ ]]; then response="n" else echo print_failed "Invalid input. Please enter 'y', 'yes', 'n', or 'no'." echo continue fi # store in the caller’s variable eval "$2='$response'" # handle it case $response in y) echo print_success "Continuing with answer: $response" echo sleep 0.2 break ;; n) echo print_msg "${C}Skipping this step${NC}" echo sleep 0.2 break ;; esac done log_debug "$1 $response" } # get the latest version from a github releases # ex. latest_tag=$(get_latest_release "$repo_owner" "$repo_name") function get_latest_release() { local repo_owner="$1" local repo_name="$2" curl -s "https://api.github.com/repos/$repo_owner/$repo_name/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' } function install_font_for_style() { local style_number="$1" print_msg "Installing Fonts..." check_and_create_directory "$HOME/.fonts" download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/$de_name/look_${style_number}/font.tar.gz" "$HOME/.fonts" fc-cache -f cd "$HOME" || return 1 } # Use:- select_an_option 8 1 variable_name function select_an_option() { local max_options=$1 local default_option=${2:-1} local response_var=$3 local response while true; do read -r -p "${Y}select an option (Default ${default_option}): ${NC}" response response=${response:-$default_option} if [[ $response =~ ^[0-9]+$ ]] && ((response >= 1 && response <= max_options)); then echo print_success "Continuing with answer: $response" sleep 0.2 eval "$response_var=$response" break else echo print_failed " Invalid input, Please enter a number between 1 and $max_options" fi done } function read_conf() { if [[ ! -f "$CONFIG_FILE" ]]; then print_failed " Configuration file $CONFIG_FILE not found" exit 0 fi # shellcheck disable=SC1090 source "$CONFIG_FILE" print_success "Configuration variables loaded" validate_required_vars } function print_to_config() { local var_name="$1" local var_value="${2:-${!var_name}}" local IFS=$' \t\n' if grep -q "^${var_name}=" "$CONFIG_FILE" 2>/dev/null; then sed -i "s|^${var_name}=.*|${var_name}=${var_value}|" "$CONFIG_FILE" else echo "${var_name}=${var_value}" >>"$CONFIG_FILE" fi log_debug "$var_name $var_value" } function validate_required_vars() { local required_vars=( # Basic system variables "HOME" "PREFIX" "TMPDIR" "PACKAGE_MANAGER" # Display and GUI variables "display_number" "gui_mode" "de_name" "de_startup" "de_on_startup" # Hardware acceleration variables "enable_hw_acc" # Configuration paths "CONFIG_FILE" "themes_folder" "icons_folder" # apps "installed_browser" "installed_ide" "installed_media_player" "installed_photo_editor" "installed_wine" # extra "chosen_shell_name" "terminal_utility_setup_answer" "fm_tools" # Distro "distro_add_answer" ) # If hardware acceleration is enabled, add required variables if [[ "$enable_hw_acc" == "y" ]]; then required_vars+=( "GPU_NAME" "exp_termux_vulkan_hw_answer" "termux_hw_answer" ) fi # If a distro is enabled, add required variables if [[ "$distro_add_answer" == "y" ]]; then required_vars+=( "selected_distro_type" "selected_distro" "pd_audio_config_answer" "pd_useradd_answer" ) fi if [[ "$distro_add_answer" == "y" ]] && [[ "$pd_useradd_answer" == "y" ]]; then required_vars+=( "user_name" ) fi if [[ "$enable_hw_acc" == "y" ]] && [[ "$distro_add_answer" == "y" ]]; then required_vars+=( "pd_hw_answer" ) fi print_msg "Validating required configuration values..." local missing_vars=() for var in "${required_vars[@]}"; do if [[ -z "${!var}" ]]; then missing_vars+=("$var") fi done if ((${#missing_vars[@]} > 0)); then print_failed "The following required configuration values are not set:" for var in "${missing_vars[@]}"; do echo " - $var" log_debug "$var" exit 1 done exit 1 fi print_success "All required variables are set" return 0 } ######################################################################### # # Ask Required Questions # ######################################################################### # check the avilable styles and create a list to type the corresponding number # in the style readme file the name must use this'## number name :' pattern, like:- ## 1. Basic Style: function questions_theme_select() { local owner="sabamdarif" local repo="termux-desktop" local main_folder="setup-files/$de_name" local branch="setup-files" # Set default style value based on the desktop environment (DE) case "$de_name" in xfce | mate) default_selection="1" ;; lxqt | openbox) default_selection="2" ;; i3wm | dwm | bspwm | awesome | fluxbox) default_selection="0" ;; *) default_selection="0" ;; esac # Get the number of available custom styles subfolder_count_value=$(count_subfolders "$owner" "$repo" "$main_folder" "$branch" 2>/dev/null) # If no custom styles are available, use stock style and skip interaction if [[ "$subfolder_count_value" -eq 0 ]]; then print_msg "No custom setup is available for $de_name" log_debug "no:- $subfolder_count_value, No custom setup is available for $de_name" print_msg "Continuing with style 0: Stock" style_answer=0 style_name="Stock" log_debug "$style_answer $subfolder_count_value" return fi # If custom styles exist, fetch and display them local styles_url="https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/docs/${de_name}_styles.md" if curl --head --silent --fail "$styles_url" >/dev/null; then print_msg "Downloading list of available styles..." check_and_delete "${current_path}/styles.md" download_file "${current_path}/styles.md" "$styles_url" else log_debug "No custom setup is available for $de_name" print_msg "Continuing with style 0: Stock" style_answer=0 style_name="Stock" log_debug "$style_answer $subfolder_count_value" return fi if [[ "$subfolder_count_value" -gt 0 ]]; then banner print_msg "Check the $de_name styles preview" echo print_msg "From Here:- ${B}https://github.com/sabamdarif/termux-desktop/blob/main/docs/${de_name}_styles.md" echo print_msg "Number of available custom styles for $de_name is: ${C}${subfolder_count_value}" echo print_msg "Available Styles Are:" echo grep -oP '## \d+\..+?(?=(\n## \d+\.|\Z))' "${current_path}/styles.md" | while read -r style; do echo "${Y}${style#### }${NC}" done while true; do echo read -r -p "${R}[${C}-${R}]${Y} Type number of the style (Press Enter to select default): ${NC}" style_answer style_answer="${style_answer:-$default_selection}" if [[ "$style_answer" =~ ^[0-9]+$ ]] && [[ "$style_answer" -ge 0 ]] && [[ "$style_answer" -le "$subfolder_count_value" ]]; then style_name=$(grep -oP "^## $style_answer\..+?(?=(\n## \d+\.|\Z))" "${current_path}/styles.md" | sed -e "s/^## $style_answer\. //" -e "s/:$//" -e 's/^[[:space:]]*//;s/[[:space:]]*$//') echo print_success "Continuing with style number ${C}$style_answer (Style: $style_name${NC})" echo break else echo print_failed "The entered style number is incorrect" echo print_msg "${Y}Please enter a number between 0 and ${subfolder_count_value}" echo print_msg "Check the $de_name styles section in GitHub" echo print_msg "${B}https://github.com/sabamdarif/termux-desktop/blob/main/docs/${de_name}_styles.md" echo fi done check_and_delete "${current_path}/styles.md" log_debug "$style_answer $subfolder_count_value" fi } function ask_to_chose_de() { # Setlect Desktop Environment banner print_msg "Importing desktop related data..." local owner="sabamdarif" local repo="termux-desktop" local branch="setup-files" # calculate availabe styles for all the desktop environments local total_custom_xfce_setup total_custom_xfce_setup=$(count_subfolders "$owner" "$repo" "setup-files/xfce" "$branch" 2>/dev/null) local total_custom_lxqt_setup total_custom_lxqt_setup=$(count_subfolders "$owner" "$repo" "setup-files/lxqt" "$branch" 2>/dev/null) local total_custom_mate_setup total_custom_mate_setup=$(count_subfolders "$owner" "$repo" "setup-files/mate" "$branch" 2>/dev/null) local total_custom_gnome_setup total_custom_gnome_setup=$(count_subfolders "$owner" "$repo" "setup-files/gnome" "$branch" 2>/dev/null) local total_custom_cinnamon_setup total_custom_cinnamon_setup=$(count_subfolders "$owner" "$repo" "setup-files/cinnamon" "$branch" 2>/dev/null) # calculate availabe styles for all the window managers local total_custom_openbox_setup total_custom_openbox_setup=$(count_subfolders "$owner" "$repo" "setup-files/openbox" "$branch" 2>/dev/null) local total_custom_i3wm_setup total_custom_i3wm_setup=$(count_subfolders "$owner" "$repo" "setup-files/i3wm" "$branch" 2>/dev/null) local total_custom_dwm_setup total_custom_dwm_setup=$(count_subfolders "$owner" "$repo" "setup-files/dwm" "$branch" 2>/dev/null) local total_custom_bspwm_setup total_custom_bspwm_setup=$(count_subfolders "$owner" "$repo" "setup-files/bspwm" "$branch" 2>/dev/null) local total_custom_awesome_setup total_custom_awesome_setup=$(count_subfolders "$owner" "$repo" "setup-files/awesome" "$branch" 2>/dev/null) local total_custom_fluxbox_setup total_custom_fluxbox_setup=$(count_subfolders "$owner" "$repo" "setup-files/fluxbox" "$branch" 2>/dev/null) local total_custom_icewm_setup total_custom_icewm_setup=$(count_subfolders "$owner" "$repo" "setup-files/icewm" "$branch" 2>/dev/null) banner print_msg "Select Desktop Environment" echo " " echo "${Y}1. XFCE($total_custom_xfce_setup)${NC}" echo echo "${Y}2. LXQT($total_custom_lxqt_setup)${NC}" echo echo "${Y}3. OPENBOX WM($total_custom_openbox_setup)${NC}" echo echo "${Y}4. MATE (Unstable)($total_custom_mate_setup)${NC}" echo echo "${Y}5. Gnome($total_custom_gnome_setup)(WIP, so expect bugs)${NC}" echo echo "${Y}6. Cinnamon($total_custom_cinnamon_setup)${NC}" echo echo "${Y}7. I3Wm($total_custom_i3wm_setup)${NC}" echo echo "${Y}8. Dwm($total_custom_dwm_setup)${NC}" echo echo "${Y}9. Bspwm($total_custom_bspwm_setup)${NC}" echo echo "${Y}10. Awesome($total_custom_awesome_setup)${NC}" echo echo "${Y}11. Fluxbox($total_custom_fluxbox_setup)${NC}" echo echo "${Y}12. IceWM($total_custom_icewm_setup)${NC}" echo select_an_option 12 1 desktop_answer # set the variables based on chosen de sys_icons_folder="$PREFIX/share/icons" sys_themes_folder="$PREFIX/share/themes" if [[ "$desktop_answer" == "1" ]]; then de_name="xfce" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="startxfce4" elif [[ "$desktop_answer" == "2" ]]; then de_name="lxqt" themes_folder="$sys_themes_folder" icons_folder="$sys_icons_folder" de_startup="startlxqt" elif [[ "$desktop_answer" == "3" ]]; then de_name="openbox" themes_folder="$sys_themes_folder" icons_folder="$sys_icons_folder" de_startup="openbox-session" elif [[ "$desktop_answer" == "4" ]]; then de_name="mate" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="mate-session" elif [[ "$desktop_answer" == "5" ]]; then de_name="gnome" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="gnome-session-minimal" elif [[ "$desktop_answer" == "6" ]]; then de_name="cinnamon" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="cinnamon-session" elif [[ "$desktop_answer" == "7" ]]; then de_name="i3wm" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="i3" elif [[ "$desktop_answer" == "8" ]]; then de_name="dwm" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="dwm" elif [[ "$desktop_answer" == "9" ]]; then de_name="bspwm" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="bspwm" elif [[ "$desktop_answer" == "10" ]]; then de_name="awesome" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="awesome" elif [[ "$desktop_answer" == "11" ]]; then de_name="fluxbox" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="fluxbox" elif [[ "$desktop_answer" == "12" ]]; then de_name="icewm" themes_folder="$HOME/.themes" icons_folder="$HOME/.icons" de_startup="icewm-session" fi banner questions_theme_select } function questions_zsh_theme_select() { print_msg "${BOLD} Select zsh theme" echo echo "${Y}1. My Zsh Theme (not customizable, made for my setup) ${NC}" echo echo "${Y}2. Powerlevel10k (highly customizable) ${NC}" echo echo "${Y}3. Pure (pretty, minimal and fast zsh prompt) ${NC}" echo select_an_option 3 1 chosen_zsh_theme if [[ "$chosen_zsh_theme" == "1" ]]; then selected_zsh_theme_name="td_zsh" elif [[ "$chosen_zsh_theme" == "2" ]]; then selected_zsh_theme_name="p10k_zsh" elif [[ "$chosen_zsh_theme" == "3" ]]; then selected_zsh_theme_name="pure_zsh" fi } function questions_nerd_font_select() { print_msg "Select nerd font you want to install...${B}" echo latest_nf_version=$(get_latest_release "ryanoasis" "nerd-fonts") release_json=$(curl -sSL "https://api.github.com/repos/ryanoasis/nerd-fonts/releases/tags/${latest_nf_version}") mapfile -t ASSET_NAMES < <( jq -r ' .assets // [] | map(select(.name | endswith(".tar.xz"))) | .[].name ' <<<"$release_json" ) FONT_DISPLAY=() for asset in "${ASSET_NAMES[@]}"; do FONT_DISPLAY+=("${asset%.tar.xz}") done ((${#ASSET_NAMES[@]} == 0)) && { print_failed "No .tar.xz fonts found for ${latest_nf_version}." >&2 exit 1 } term_width=$(tput cols 2>/dev/null || echo 80) ( for i in "${!FONT_DISPLAY[@]}"; do printf "%3d) %s\n" "$((i + 1))" "${FONT_DISPLAY[$i]}" done ) | pr -2 -t -w"$term_width" echo select_an_option "${#ASSET_NAMES[@]}" 1 nerd_choice sel_asset_name="${ASSET_NAMES[$((nerd_choice - 1))]}" sel_base_name="${FONT_DISPLAY[$((nerd_choice - 1))]}" } function questions_setup_manual() { ask_to_chose_de banner print_msg "${BOLD}Select browser you want to install" echo echo "${Y}1. firefox${NC}" echo echo "${Y}2. chromium${NC}" echo echo "${Y}3. firefox & chromium (both)${NC}" echo echo "${Y}4. Skip${NC}" echo select_an_option 4 1 browser_answer case "$browser_answer" in 1) installed_browser="firefox" ;; 2) installed_browser="chromium" ;; 3) installed_browser="all" ;; 4) installed_browser="skip" ;; esac banner print_msg "${BOLD}Select IDE you want to install" echo echo "${Y}1. VS Code${NC}" echo echo "${Y}2. Geany${NC}" echo echo "${Y}3. NeoVim${NC}" echo echo "${Y}4. All of them${NC}" echo echo "${Y}5. Skip${NC}" echo select_an_option 5 1 ide_answer case "$ide_answer" in 1) installed_ide="code" ;; 2) installed_ide="geany" ;; 3) installed_ide="neovim" ;; 4) installed_ide="all" ;; 5) installed_ide="skip" ;; esac echo if [[ "$installed_ide" == "neovim" ]] || [[ "$installed_ide" == "all" ]]; then print_msg "${BOLD}Select neovim config" echo echo "${Y}1. Stock${NC}" echo echo "${Y}2. NvChad${NC}" echo echo "${Y}3. LazyVim${NC}" echo echo "${Y}4. mynvim (my personal neovim config)${NC}" echo select_an_option 4 2 select_neovim_distro case "$select_neovim_distro" in 1) installed_nvim_distro="stock" ;; 2) installed_nvim_distro="nvchad" ;; 3) installed_nvim_distro="lazyvim" ;; 4) installed_nvim_distro="mynvim" ;; esac fi banner print_msg "${BOLD}Select Media Player you want to install" echo echo "${Y}1. Vlc${NC}" echo echo "${Y}2. Mpv${NC}" echo echo "${Y}3. Both${NC}" echo echo "${Y}4. Skip${NC}" echo select_an_option 4 1 player_answer case "$player_answer" in 1) installed_media_player="vlc" ;; 2) installed_media_player="mpv" ;; 3) installed_media_player="all" ;; 4) installed_media_player="skip" ;; esac banner print_msg "${BOLD}Select Photo Editor${NC}" echo echo "${Y}1. Gimp${NC}" echo echo "${Y}2. Inkscape${NC}" echo echo "${Y}3. Gimp & Inkscape (both)${NC}" echo echo "${Y}4. Skip${NC}" echo select_an_option 4 1 photo_editor_answer case "$photo_editor_answer" in 1) installed_photo_editor="gimp" ;; 2) installed_photo_editor="inkscape" ;; 3) installed_photo_editor="all" ;; 4) installed_photo_editor="skip" ;; esac banner print_msg "${BOLD}Do you want to install wine in termux ${C}(without proot-distro)" echo echo "${Y}1. Native ${C}(can run only arm64 based exe)${NC}" echo echo "${Y}2. Mobox ${C}(Un-maintained) ${NC}" echo print_msg "${B}Know More About Mobox:- https://github.com/olegos2/mobox/" echo echo "${Y}3. Wine Hangover${NC}" echo echo "${Y}4. Skip${NC}" echo select_an_option 4 1 wine_answer case "$wine_answer" in 1) installed_wine="stock" ;; 2) installed_wine="mobox" ;; 3) installed_wine="wine_hangover" ;; 4) installed_wine="skip" ;; esac banner confirmation_y_or_n "Do you want to Configure Hardware Acceleration" enable_hw_acc banner print_msg " By default, it only adds 4-5 wallpapers" echo print_msg "${R}This is a 1GB+ collection (Thanks:-JaKooLit)" echo confirmation_y_or_n "Do you want to add some more wallpapers" ext_wall_answer banner print_msg "${BOLD}Select Your shell${NC}" echo echo "${Y}1. Zsh + zinit${NC}" echo echo "${Y}2. Custom Bash prompt + ble.sh (ble.sh kind of buggy right now)${NC}" echo echo "${Y}3. Custom Bash prompt${NC}" echo select_an_option 4 1 chosen_shell_answer case "$chosen_shell_answer" in 1) chosen_shell_name="zsh" ;; 2) chosen_shell_name="bash_with_ble" ;; 3) chosen_shell_name="bash" ;; esac if [[ "$chosen_shell_name" == "zsh" ]]; then questions_zsh_theme_select fi banner echo print_msg "${B}Know More About Terminal Utility:- https://github.com/sabamdarif/termux-desktop/blob/main/docs/see-more.md#hammer_and_wrenchlearn-about-terminal-utilities" echo confirmation_y_or_n "Do you want install some terminal utility to make better terminal exprience" terminal_utility_setup_answer banner questions_nerd_font_select banner echo -e "${R}[${C}-${R}]${B} File Manager Tools Enhancement${NC} ${B}Overview:${NC} This option enhances your file manager with powerful right-click menu features. ${B}Key Features:${NC} • Media Operations - Video processing and conversion - Image editing and optimization - Audio file management - PDF manipulation • File Management - Archive compression/extraction - File permissions control - Document processing - File encryption - Hash verification • Additional Features - Custom scripts integration - Batch processing - Quick actions menu ${B}How to Access:${NC} Access these features through the 'Scripts' menu in your file manager's right-click context menu. ${NC}" confirmation_y_or_n "Do you want File Manager Tools tailored with powerful extra features" fm_tools banner print_msg "${BOLD} Select Gui Mode" echo echo "${Y}1. Termux:x11${NC}" echo echo "${Y}2. Both Termux:x11 and VNC${NC}" echo select_an_option 2 1 gui_mode_num # set gui_mode and display_number value if [[ "$gui_mode_num" == "1" ]]; then gui_mode="termux_x11" display_number="0" gui_mode_name="Termux:x11" elif [[ "$gui_mode_num" == "2" ]]; then gui_mode="both" display_number="0" gui_mode_name="Both" fi banner confirmation_y_or_n "Do you want to start the desktop at Termux startup" de_on_startup if [[ "$de_on_startup" == "y" && "$gui_mode" == "both" ]]; then print_msg "You chose both vnc and termux:x11 to access gui mode" echo print_msg "Which will be your default" echo echo "${Y}1. Termux:x11${NC}" echo echo "${Y}2. Vnc${NC}" echo select_an_option 2 1 autostart_gui_mode_num if [[ "$autostart_gui_mode_num" == "1" ]]; then default_gui_mode="termux_x11" elif [[ "$autostart_gui_mode_num" == "2" ]]; then default_gui_mode="vnc" fi fi banner echo -e " ${R}[${C}-${R}]${G}${BOLD} Linux Distro Container:- ${NC} It will help you to install apps that aren't available in Termux. So it will set up a Linux distro container and add options to install those apps. Also, you can launch those installed apps from Termux like other apps. " echo "Learn More:- https://github.com/sabamdarif/termux-desktop/blob/main/docs/proot-container.md" echo confirmation_y_or_n "Do you want to add a Linux container" distro_add_answer } function setup_device_gpu_model() { if [[ -z "$GPU_NAME" ]] || [[ "$GPU_NAME" == "unknown" ]]; then while true; do banner print_warn "Unable to auto detect GPU" echo print_msg "${BOLD}Please Select Your Device GPU" echo echo "${Y}1. Adreno${NC}" echo echo "${Y}2. Mali${NC}" echo echo "${Y}3. Xclipse${NC}" echo echo "${Y}4. Others (Unstable)${NC}" echo read -r -p "${Y} Enter your choise [1-4]: ${NC}" device_gpu_model if [[ "$device_gpu_model" =~ ^[1-4]$ ]]; then print_success "Continuing with answer: $device_gpu_model" break else print_warn "Invalid input, Please enter a number between 1 and 4" fi done # set gpu model name case "$device_gpu_model" in 1) GPU_NAME="adreno" ;; 2) GPU_NAME="mali" ;; 3) GPU_NAME="xclipse" ;; 4) GPU_NAME="others" ;; esac fi } # distro hardware accelrration related questions function distro_hw_questions() { if [[ "$distro_add_answer" == "y" ]]; then case "$termux_hw_answer" in "virgl" | "virgl_vulkan") if [[ "$GPU_NAME" == "adreno" ]]; then banner print_msg "${BOLD}Select Hardware Acceleration Driver For Linux Container" echo "${Y}1. VirGL + ANGLE (GPU Passthrough via virpipe)${NC}" echo echo "${Y}2. Turnip (Native Adreno Vulkan Driver)${NC}" echo select_an_option 2 1 pd_hw_answer_num case "$pd_hw_answer_num" in 1) pd_hw_answer="virgl" ;; 2) pd_hw_answer="turnip" ;; esac pd_hw_answer=$([ "$pd_hw_answer_num" == "1" ] && echo "virgl" || echo "turnip") else pd_hw_answer="virgl" fi ;; "freedreno_kgsl" | "mesa_freedreno" | "mesa_zink_freedreno") pd_hw_answer="turnip" ;; *) banner print_msg "${BOLD}Select Hardware Acceleration Driver For Linux Container" echo print_msg "If You Skip It, It Will Use The Previous Selection" echo echo "${Y}1. Mesa Zink (Vulkan-to-OpenGL Translation)${NC}" echo echo "${Y}2. VirGL (GPU Passthrough via virpipe)${NC}" echo echo "${Y}3. Turnip (Native Adreno Vulkan Driver)${NC}" echo select_an_option 3 1 pd_hw_answer_num case "$pd_hw_answer_num" in 1) pd_hw_answer="zink" ;; 2) pd_hw_answer="virgl" ;; 3) pd_hw_answer="turnip" ;; esac ;; esac fi } # hardware accelrration related questions #NOTE: this get called first in hw_questions function function exp_vulkan_support() { print_msg "${BOLD}First Read This" echo print_msg "${B}This:- https://github.com/sabamdarif/termux-desktop/blob/main/docs/hw-acceleration.md" echo print_msg "${BOLD}Select the vulkan driver" echo if [[ "${termux_arch}" == "aarch64" ]]; then echo "${Y}1. vulkan-wrapper-android${NC}" echo echo "${Y}2. vulkan-wrapper-android (leegao's fork)${NC}" echo echo "${Y}3. mesa-vulkan-icd-freedreno (Turnip) (adreno only)${NC}" echo echo "${Y}4. mesa-zink-vulkan-icd-freedreno (Turnip) (adreno only)${NC}" echo echo "${Y}5. mesa-vulkan-icd-freedreno (Kgsl) (adreno only)${NC}" echo echo "${Y}6. will use the old virgl way${NC}" echo select_an_option 6 1 exp_termux_vulkan_hw_answer_num # set gpu api name case "$exp_termux_vulkan_hw_answer_num" in 1) exp_termux_vulkan_hw_answer="vulkan_wrapper_android" ;; 2) exp_termux_vulkan_hw_answer="vulkan_wrapper_android_leegaos_fork" ;; 3) exp_termux_vulkan_hw_answer="mesa_freedreno" ;; 4) exp_termux_vulkan_hw_answer="mesa_zink_freedreno" ;; 5) exp_termux_vulkan_hw_answer="freedreno_kgsl" ;; 6) exp_termux_vulkan_hw_answer="skip" ;; esac else echo "${Y}1. vulkan-wrapper-android${NC}" echo echo "${Y}2. mesa-vulkan-icd-freedreno (Turnip) (adreno only)${NC}" echo echo "${Y}3. mesa-zink-vulkan-icd-freedreno (Turnip) (adreno only)${NC}" echo echo "${Y}4. mesa-vulkan-icd-freedreno (Kgsl) (adreno only)${NC}" echo echo "${Y}5. will use the old virgl way${NC}" echo select_an_option 5 1 exp_termux_vulkan_hw_answer_num # set gpu api name case "$exp_termux_vulkan_hw_answer_num" in 1) exp_termux_vulkan_hw_answer="vulkan_wrapper_android" ;; 2) exp_termux_vulkan_hw_answer="mesa_freedreno" ;; 3) exp_termux_vulkan_hw_answer="mesa_zink_freedreno" ;; 4) exp_termux_vulkan_hw_answer="freedreno_kgsl" ;; 5) exp_termux_vulkan_hw_answer="skip" ;; esac fi } function exp_termux_gl_hw_support() { banner echo print_msg "${BOLD}It will be used to enable opengl support" echo echo "${Y}1. Mesa Zink (Vulkan-to-OpenGL) + VirGL Server${NC}" echo echo "${Y}2. VirGL (GPU Passthrough via virpipe)${NC}" echo echo "${Y}3. VirGL + ANGLE OpenGL Backend${NC}" echo echo "${Y}4. VirGL + ANGLE Vulkan Backend${NC}" echo echo "${Y}5. Mesa Zink + VirGL (Vulkan-to-OpenGL via VirGL)${NC}" echo echo "${Y}6. Mesa Zink Direct (Native Vulkan-to-OpenGL)${NC}" echo echo "${Y}7. Mesa Zink Direct with Mesa-zink (Native Vulkan-to-OpenGL)${NC}" echo select_an_option 7 1 exp_termux_gl_hw_answer_num # set gpu api name case "$exp_termux_gl_hw_answer_num" in 1) exp_termux_gl_hw_answer="zink" ;; 2) exp_termux_gl_hw_answer="virgl" ;; 3) exp_termux_gl_hw_answer="virgl_angle" ;; 4) exp_termux_gl_hw_answer="virgl_vulkan" ;; 5) exp_termux_gl_hw_answer="zink_virgl" ;; 6) exp_termux_gl_hw_answer="zink_with_mesa" ;; 7) exp_termux_gl_hw_answer="zink_with_mesa_zink" ;; esac termux_hw_answer="${exp_termux_gl_hw_answer}" distro_hw_questions } #NOTE: it first call exp_vulkan_support then if user select vulkan_wrapper_android the it will go for exp_termux_gl_hw_answer (as name suggest it setup the opengl driver for termux) and user type 4=skip then it will go for everything using virgl option (it's kind of same as exp_termux_gl_hw_answer), then when it done for termux part it will call distro_hw_questions to setup hwa for the selected proot-distro function hw_questions() { banner exp_vulkan_support if [[ "$exp_termux_vulkan_hw_answer" == "vulkan_wrapper_android" ]] || [[ "$exp_termux_vulkan_hw_answer" == "vulkan_wrapper_android_leegaos_fork" ]] || [[ "$exp_termux_vulkan_hw_answer" == "mesa_freedreno" ]] || [[ "$exp_termux_vulkan_hw_answer" == "mesa_zink_freedreno" ]]; then exp_termux_gl_hw_support elif [[ "$exp_termux_vulkan_hw_answer" == "freedreno_kgsl" ]]; then termux_hw_answer="${exp_termux_vulkan_hw_answer}" distro_hw_questions elif [[ "$exp_termux_vulkan_hw_answer" == "skip" ]]; then print_msg "${BOLD}First Read This" echo print_msg "${B}This:- https://github.com/sabamdarif/termux-desktop/blob/main/docs/hw-acceleration.md" echo print_msg "${BOLD}Select Hardware Acceleration API" echo echo print_msg "${BOLD}Select Hardware Acceleration API" echo echo "${Y}1. Mesa Zink (Vulkan-to-OpenGL) + VirGL Server${NC}" echo echo "${Y}2. VirGL (GPU Passthrough via virpipe)${NC}" echo echo "${Y}3. VirGL + ANGLE OpenGL Backend${NC}" echo echo "${Y}4. VirGL + ANGLE Vulkan Backend${NC}" echo echo "${Y}5. Mesa Zink + VirGL (Vulkan-to-OpenGL via VirGL)${NC}" echo select_an_option 5 1 termux_hw_answer_num # set gpu api name case "$termux_hw_answer_num" in 1) termux_hw_answer="zink" ;; 2) termux_hw_answer="virgl" ;; 3) termux_hw_answer="virgl_angle" ;; 4) termux_hw_answer="virgl_vulkan" ;; 5) termux_hw_answer="zink_virgl" ;; esac distro_hw_questions fi } # distro related questions function distro_type_select() { print_msg "${BOLD}Select the distro type" echo " " echo "${G}chroot-distro:- ${B}https://github.com/sabamdarif/chroot-distro${NC}" echo " " echo "${G}proot-distro:- ${B}https://github.com/termux/proot-distro${NC}" echo " " echo "${Y}1. Proot Distro${NC}" echo " " echo "${Y}2. Chroot Distro${NC}" echo " " select_an_option 2 1 distro_type_answer case "$distro_type_answer" in 1) selected_distro_type="proot" ;; 2) selected_distro_type="chroot" ;; *) selected_distro_type="proot" ;; esac } function choose_distro() { print_msg "${BOLD}Select Linux Distro You Want To Add" echo " " echo "${Y}1. Debian${NC}" echo " " echo "${Y}2. Ubuntu${NC}" echo " " echo "${Y}3. Arch (Unstable | isn't fully suppoted by AppStore yet)${NC}" echo " " echo "${Y}4. Fedora${NC}" echo " " select_an_option 4 1 distro_answer case "$distro_answer" in 1) selected_distro="debian" ;; 2) selected_distro="ubuntu" ;; 3) selected_distro="archlinux" ;; 4) selected_distro="fedora" ;; *) selected_distro="debian" ;; esac } function setup_user_name_only() { echo print_msg "${BOLD}Create user account" echo while true; do echo " " print_msg "Default Password Will Be Set, Because Sometimes It Might Ask You For Password" echo print_msg "Password:-${C}root" # set password to root pass=root echo while true; do read -r -p "${R}[${C}-${R}]${G} Input username [Lowercase]: ${NC}" user_name if [[ -z "$user_name" ]]; then print_warn "You can't leave the username empty. Please enter a valid username." elif [[ "$user_name" =~ \ ]]; then print_warn "Username cannot contain spaces. Please enter a valid username." else break fi done echo local choice read -r -p "${R}[${C}-${R}]${Y} Do you want to continue with username ${C}$user_name ${Y}? (y/n) : ${NC}" choice echo choice="${choice:-y}" echo print_success "Continuing with answer: $choice" sleep 0.2 case $choice in [yY]*) print_success "Continuing with username ${C}$user_name" break ;; [nN]*) print_msg "Please provide username again." echo ;; *) print_failed "Invalid input, Please enter y or n" ;; esac done } function setup_user_name_and_pass() { echo print_msg "${BOLD}Create user account" echo while true; do while true; do read -r -p "${R}[${C}-${R}]${G}Input username [Lowercase]: ${NC}" user_name if [[ -z "$user_name" ]]; then print_warn "You can't leave the username empty. Please enter a valid username." elif [[ "$user_name" =~ \ ]]; then print_warn "Username cannot contain spaces. Please enter a valid username." else break fi done echo while true; do read -r -p "${R}[${C}-${R}]${G}Input Password (Minimum 4 characters): ${NC}" pass if [[ -z "$pass" ]]; then print_warn "You can't leave the password empty. Please enter a valid password." elif [[ "$user_name" =~ \ ]]; then print_warn "Password cannot contain spaces. Please enter a valid username." elif [[ ${#pass} -lt 4 ]]; then print_warn "Password must be at least 4 characters long. Please enter a longer password." else break fi done echo read -r -p "${R}[${C}-${R}]${Y}Do you want to continue with username ${C}$user_name ${Y}and password ${C}$pass${Y} ? (y/n) : ${NC}" choice echo choice="${choice:-y}" echo print_success "Continuing with answer: $choice" echo "" sleep 0.2 case $choice in [yY]*) print_success "Continuing with username ${C}$user_name ${G}and password ${C}$pass" break ;; [nN]*) print_msg "Please provide username and password again." echo ;; *) print_failed "Invalid input, Please enter y or n" ;; esac done } function distro_questions() { banner distro_type_select choose_distro banner confirmation_y_or_n "Do you want to configure audio support for Linux distro container" pd_audio_config_answer banner confirmation_y_or_n "Do you want to create a normal user account ${C}(Recomended)" pd_useradd_answer echo if [[ "$pd_useradd_answer" == "n" ]]; then print_msg "Skiping User Account Setup" else print_msg "${BOLD}Select user account type" echo echo "${Y}1. User with no password confirmation${NC}" echo echo "${Y}2. User with password confirmation${NC}" echo select_an_option 2 1 pd_pass_type if [[ "$pd_pass_type" == "1" ]]; then setup_user_name_only elif [[ "$pd_pass_type" == "2" ]]; then setup_user_name_and_pass fi fi } # it set all the value that wil be used for printing the setup configuration (in print_conf_info) function define_value_name() { # Gui mode if [[ "$gui_mode" == "termux_x11" ]]; then gui_mode_name="Termux:x11" elif [[ "$gui_mode" == "both" ]]; then gui_mode_name="Both" fi # autostart value if [[ "$de_on_startup" == "y" ]]; then autostart_value="Yes" elif [[ "$de_on_startup" == "n" ]]; then autostart_value="No" fi # browser if [[ "$installed_browser" == "firefox" ]]; then browser_name="Firefox" elif [[ "$installed_browser" == "chromium" ]]; then browser_name="Chromium" elif [[ "$installed_browser" == "all" ]]; then browser_name="Both Firefox and Chromium" elif [[ "$installed_browser" == "skip" ]]; then browser_name="Skip" fi # media player if [[ "$installed_media_player" == "vlc" ]]; then media_player_name="Vlc" elif [[ "$installed_media_player" == "mpv" ]]; then media_player_name="Mpv" elif [[ "$installed_media_player" == "all" ]]; then media_player_name="Both Vlc and Mpv" elif [[ "$installed_media_player" == "skip" ]]; then media_player_name="Skip" fi # Image Editor if [[ "$installed_photo_editor" == "gimp" ]]; then photo_editor_name="GIMP" elif [[ "$installed_photo_editor" == "inkscape" ]]; then photo_editor_name="Inkscape" elif [[ "$installed_photo_editor" == "all" ]]; then photo_editor_name="Both GIMP and Inkscape" elif [[ "$installed_photo_editor" == "skip" ]]; then photo_editor_name="Skip" fi # IDE if [[ "$installed_ide" == "code" ]]; then ide_name="VS Code (code-oss)" elif [[ "$installed_ide" == "geany" ]]; then ide_name="Geany" elif [[ "$installed_ide" == "neovim" ]]; then if [[ "$installed_nvim_distro" == "stock" ]]; then neovim_distro="Stock" elif [[ "$installed_nvim_distro" == "nvchad" ]]; then neovim_distro="NvChad" elif [[ "$installed_nvim_distro" == "lazyvim" ]]; then neovim_distro="LazyVim" elif [[ "$installed_nvim_distro" == "mynvim" ]]; then neovim_distro="MyNvim" fi ide_name="NeoVim ${neovim_distro}" elif [[ "$installed_ide" == "all" ]]; then ide_name="All" elif [[ "$installed_ide" == "skip" ]]; then ide_name="Skip" fi # WINE if [[ "$installed_wine" == "stock" ]]; then wine_type_name="Native" elif [[ "$installed_wine" == "mobox" ]]; then wine_type_name="Mobox" elif [[ "$installed_wine" == "wine_hangover" ]]; then wine_type_name="Wine Hangover" elif [[ "$installed_wine" == "skip" ]]; then wine_type_name="Skip" fi # Extra Wallpapers if [[ "$ext_wall_answer" == "y" ]]; then ext_wall_answer_confirmation="Yes" elif [[ "$ext_wall_answer" == "n" ]]; then ext_wall_answer_confirmation="No" fi # File Manager Tools if [[ "$fm_tools" == "y" ]]; then fm_tools_confirmation="Yes" elif [[ "$fm_tools" == "n" ]]; then fm_tools_confirmation="No" fi # Shell if [[ "$chosen_shell_name" == "bash" ]]; then current_shell_name="Bash" elif [[ "$chosen_shell_name" == "bash_with_ble" ]]; then current_shell_name="Bash (With Ble.sh)" elif [[ "$chosen_shell_name" == "zsh" ]]; then if [[ "$selected_zsh_theme_name" == "td_zsh" ]]; then zsh_theme_name="My Zsh Theme" elif [[ "$selected_zsh_theme_name" == "p10k_zsh" ]]; then zsh_theme_name="Powerlevel10k" elif [[ "$selected_zsh_theme_name" == "pure_zsh" ]]; then zsh_theme_name="Pure" fi current_shell_name="Zsh ($zsh_theme_name)" fi # Terminal Utilities if [[ "$terminal_utility_setup_answer" == "y" ]]; then terminal_utility_setup_confirmation="Yes" elif [[ "$terminal_utility_setup_answer" == "n" ]]; then terminal_utility_setup_confirmation="No" fi # Nerd Font if [[ "$install_type_answer" == "1" ]]; then sel_font_name="$sel_base_name" elif [[ "$install_type_answer" == "2" ]] || [[ "$install_type_answer" == "3" ]]; then sel_font_name="0xProto" else sel_font_name="N/A" fi # Hardware Acceleration Status if [[ "$enable_hw_acc" == "y" ]]; then hw_acc_confirmation="Enabled" elif [[ "$enable_hw_acc" == "n" ]]; then hw_acc_confirmation="Disabled" fi # Vulkan Driver if [[ "$exp_termux_vulkan_hw_answer" == "vulkan_wrapper_android" ]]; then vulkan_driver_name="Vulkak Wrapper Android" elif [[ "$exp_termux_vulkan_hw_answer" == "vulkan_wrapper_android_leegaos_fork" ]]; then vulkan_driver_name="Vulkan Wrapper Android (leegao's fork)" elif [[ "$exp_termux_vulkan_hw_answer" == "mesa_freedreno" ]]; then vulkan_driver_name="Mesa ICD Freedreno" elif [[ "$exp_termux_vulkan_hw_answer" == "mesa_zink_freedreno" ]]; then vulkan_driver_name="Mesa Zink ICD Freedreno" else vulkan_driver_name="Might Not Support" fi # OpenGL Driver if [[ "$termux_hw_answer" == "zink" ]]; then opengl_driver_name="Zink" elif [[ "$termux_hw_answer" == "virgl" ]]; then opengl_driver_name="Virgl" elif [[ "$termux_hw_answer" == "virgl_angle" ]]; then opengl_driver_name="Virgl Angle" elif [[ "$termux_hw_answer" == "virgl_vulkan" ]]; then opengl_driver_name="VIRGL ANGLE (Vulkan)" elif [[ "$termux_hw_answer" == "zink_virgl" ]]; then opengl_driver_name="OpenGL ES (ZINK VIRGL)" elif [[ "$termux_hw_answer" == "zink_with_mesa" ]]; then opengl_driver_name="The vulkan-wrapper-android Driver With Mesa" elif [[ "$termux_hw_answer" == "zink_with_mesa_zink" ]]; then opengl_driver_name="The vulkan-wrapper-android Driver With Mesa-Zink" elif [[ "$termux_hw_answer" == "freedreno" ]]; then opengl_driver_name="Freedreno" else opengl_driver_name="Might Not Support" fi # Linux Distro Container if [[ "$distro_add_answer" == "y" ]]; then distro_container_confirmation="Enabled" elif [[ "$distro_add_answer" == "n" ]]; then distro_container_confirmation="Disabled" fi if [[ "$selected_distro_type" == "chroot" ]]; then distro_type=CHROOT elif [[ "$selected_distro_type" == "proot" ]]; then distro_type=PROOT else distro_type="Unable to select distro type" fi # Distro User and Pass if [[ "$pd_useradd_answer" == "y" ]]; then distro_user_name="${user_name}" if [[ -z "$pass" ]]; then distro_pass="root (password will be disabled by default)" else distro_pass="${pass}" fi elif [[ "$pd_useradd_answer" == "n" ]]; then distro_user_name="Null" distro_pass="Null" fi # Distro Audio Support if [[ "$pd_audio_config_answer" == "y" ]]; then pd_audio_config_confirmation="Yes" elif [[ "$pd_audio_config_answer" == "n" ]]; then pd_audio_config_confirmation="No" fi # Distro Hardware Acceleration if [[ "$enable_hw_acc" == "y" ]]; then distro_hw_acc_confirmation="Enabled" elif [[ "$enable_hw_acc" == "n" ]]; then distro_hw_acc_confirmation="Disabled" fi # Distro Vulkan Driver if [[ "$pd_hw_answer" == "zink" ]]; then distro_vulkan_driver="Not Supported" elif [[ "$pd_hw_answer" == "virgl" ]]; then distro_vulkan_driver="Not Supported" elif [[ "$pd_hw_answer" == "turnip" ]]; then distro_vulkan_driver="Turnip" elif [[ "$pd_hw_answer" == "freedreno" ]]; then distro_vulkan_driver="Freedreno" else distro_vulkan_driver="Unable to select" fi # Distro OpenGL Driver if [[ "$pd_hw_answer" == "zink" ]]; then distro_opengl_driver="Zink" elif [[ "$pd_hw_answer" == "virgl" ]]; then distro_opengl_driver="Virgl" elif [[ "$pd_hw_answer" == "virgl" ]]; then distro_opengl_driver="Virgl" elif [[ "$pd_hw_answer" == "turnip" ]]; then distro_opengl_driver="Turnip" elif [[ "$pd_hw_answer" == "freedreno" ]]; then distro_opengl_driver="Freedreno" else distro_opengl_driver="Unable to select" fi # Distro Terminal Utilities if [[ "$terminal_utility_setup_answer" == "y" ]]; then distro_terminal_utility_setup_confirmation="Yes" elif [[ "$terminal_utility_setup_answer" == "n" ]]; then distro_terminal_utility_setup_confirmation="No" fi } function print_conf_info() { define_value_name trap '' SIGINT SIGTSTP banner print_msg "Installation Configuration Summary" echo echo "${G}Desktop Environment${NC}" echo " • Desktop: $(echo "$de_name" | tr '[:lower:]' '[:upper:]')" echo " • Desktop Style: ${style_answer}) ${style_name}" echo " • GUI Access: ${gui_mode_name}" echo " • Auto-start: ${autostart_value}" sleep 0.015 echo "${G}Applications${NC}" echo " • Browser: ${browser_name}" echo " • Media Player: ${media_player_name}" echo " • Image Editor: ${photo_editor_name}" echo " • IDE: ${ide_name}" echo " • WINE: ${wine_type_name}" sleep 0.015 echo "${G}Customization${NC}" echo " • Extra Wallpapers: ${ext_wall_answer_confirmation}" echo " • File Manager Tools: ${fm_tools_confirmation}" sleep 0.015 echo "${G}Terminal Setup${NC}" echo " • Shell: ${current_shell_name}" echo " • Terminal Utilities: ${terminal_utility_setup_confirmation}" echo " • Font: ${sel_font_name}" sleep 0.015 echo "${G}Hardware Acceleration${NC}" echo " • Status: ${hw_acc_confirmation}" if [[ "$enable_hw_acc" == "y" ]]; then echo " • GPU: $(echo "$GPU_NAME" | tr '[:lower:]' '[:upper:]')" echo " • Vulkan Driver: ${vulkan_driver_name}" echo " • OpenGL Driver: ${opengl_driver_name}" fi sleep 0.015 echo "${G}Linux Distro Container${NC}" echo " • Distro Status: ${distro_container_confirmation}" if [[ "$distro_add_answer" == "y" ]]; then echo " • Distro Type: ${distro_type}" echo " • Distribution: ${selected_distro}" echo " • Distro Username: ${distro_user_name}" echo " • Distro Pass: ${distro_pass}" echo " • Audio Support: ${pd_audio_config_confirmation}" fi if [[ "$enable_hw_acc" == "y" ]]; then echo " • Hardware Acceleration: ${distro_hw_acc_confirmation}" echo " • Vulkan Driver: ${distro_vulkan_driver}" echo " • OpenGL Driver: ${distro_opengl_driver}" fi echo " • Terminal Utilities: ${distro_terminal_utility_setup_confirmation}" sleep 0.015 # Re-enable keyboard interruptions trap - SIGINT SIGTSTP wait_for_keypress } ######################################################################### # # Select Install Type and load config # ######################################################################### function questions_install_type() { banner # Clear screen and show title first print_msg "A Quick Overview" echo sleep 0.2 echo -e "${R}[${C}-${R}]${G} Key Terms:${NC} • Generic: Pre-configured options that so far work best in most of the devices\n • Recommended: Tested configurations with minimal known issues\n • Hardware Acceleration: Uses your device's GPU for better graphics render\n • Custom: Full control over all installation options\n " echo "${R}[${Y}!${R}]${R} Important Note: ${NC}" echo -e "${B} Generic is only recomended for beginners\n For most users who are familiar with Termux, the custom option is recommended, as most features are only available in the custom option ${NC}" # Show selection options print_msg "Select Install Type" echo " " echo "${Y}1. Custom${NC}" echo " " echo "${Y}2. Generic (with hardware acceleration)${NC}" echo " " echo "${Y}3. Generic (without hardware acceleration)${NC}" echo " " select_an_option 3 1 install_type_answer if [[ "$install_type_answer" == "1" ]]; then questions_setup_manual elif [[ "$install_type_answer" == "2" ]]; then ###################################################################### # ********* Generic Recomended With Hardware Acceleration ********** # ###################################################################### ask_to_chose_de setup_device_gpu_model # download configuration download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/generic.conf" # shellcheck disable=SC1091 source generic.conf check_and_delete "generic.conf" local device_brand_name device_brand_name=$(getprop ro.product.brand | cut -d ' ' -f 1) if [[ "$GPU_NAME" == "adreno" ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/hwa/adreno/generic-adreno.conf" # shellcheck disable=SC1091 source generic-adreno.conf check_and_delete "generic-adreno.conf" elif [[ "$GPU_NAME" == "mali" ]]; then if [[ $device_brand_name == samsung* ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/hwa/mali/samsung/generic-samsung-mali.conf" # shellcheck disable=SC1091 source generic-samsung-mali.conf check_and_delete "generic-samsung-mali.conf" else download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/hwa/mali/generic-mali.conf" # shellcheck disable=SC1091 source generic-mali.conf check_and_delete "generic-mali.conf" fi else download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/hwa/generic-others.conf" # shellcheck disable=SC1091 source generic-others.conf check_and_delete "generic-others.conf" fi # setup extra config if it's lite mode install if [[ "$LITE_MODE" == "1" || "$LITE_MODE" == "true" ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/generic-lite.conf" # shellcheck disable=SC1091 source generic-lite.conf check_and_delete "generic-lite.conf" fi # create username for distro banner setup_user_name_only elif [[ "$install_type_answer" == "3" ]]; then ###################################################################### # ******* Generic Recomended Without Hardware Acceleration ********* # ###################################################################### ask_to_chose_de # download configuration download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/generic.conf" # shellcheck disable=SC1091 source generic.conf download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/nohwa/generic-nohwa.conf" # shellcheck disable=SC1091 source generic-nohwa.conf check_and_delete "generic-nohwa.conf" # setup extra config if it's lite mode install if [[ "$LITE_MODE" == "1" || "$LITE_MODE" == "true" ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/configuration/generic/generic-lite.conf" # shellcheck disable=SC1091 source generic-lite.conf check_and_delete "generic-lite.conf" fi # create username for distro banner setup_user_name_only fi } function load_local_config() { banner local config_path="$1" # Check if the file exists if [[ ! -f "$config_path" ]]; then print_failed "$config_path does not exist." exit 1 fi # Check if the file has a .conf extension if [[ "$config_path" != *.conf ]]; then print_failed "$config_path does not have a .conf extension." exit 1 fi # Check if the file is not empty (not 0KB) if [[ ! -s "$config_path" ]]; then print_failed "$config_path is empty." exit 1 fi print_success "Using the local configuration file..." # shellcheck disable=SC1090 source "$config_path" sleep 3 validate_required_vars } ######################################################################### # # Update System, Install Required Packages Repo, Requirements checkup # ######################################################################### function chose_mirror() { print_msg "${BOLD}Selecting best termux packages mirror please wait" # unlink "$PREFIX/etc/termux/chosen_mirrors" &>/dev/null # ln -s "$PREFIX/etc/termux/mirrors/all" "$PREFIX/etc/termux/chosen_mirrors" &>/dev/null # pkg --check-mirror update if [[ "$PACKAGE_MANAGER" == "apt" ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/termux-fastest-repo" chmod +x termux-fastest-repo ./termux-fastest-repo check_and_delete "termux-fastest-repo" fi } function update_sys() { banner if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then print_msg "${BOLD}Updating System...." pacman -Syu --noconfirm else print_msg "Do you want to run a speed test to find the fastest repo for you?" echo "The speed test will check all mirrors in all" echo "mirror groups, or only the group you selected." echo "This process may take some time." confirmation_y_or_n "Do you want to continue" confirmation_speedtest if [[ "$confirmation_speedtest" == "y" ]]; then chose_mirror fi print_msg "${BOLD}Updating System...." apt update -y -o Dpkg::Options::="--force-confnew" apt upgrade -y -o Dpkg::Options::="--force-confnew" fi } function get_termux_arch() { APP_ARCH=$(uname -m) SUPPORTED_ARCH="$(getprop ro.product.cpu.abilist)" case "$APP_ARCH" in aarch64) termux_arch="aarch64" ;; armv7* | arm | armv8*) termux_arch="arm" ;; esac } function try_to_autodetect_gpu() { local gpu_egl local gpu_vulkan gpu_egl=$(getprop ro.hardware.egl) gpu_vulkan=$(getprop ro.hardware.vulkan) detected_gpu="$(echo -e "$gpu_egl\n$gpu_vulkan" | sort -u | tr '\n' ' ' | sed 's/ $//')" if echo "$detected_gpu" | grep -iq "adreno"; then GPU_NAME="adreno" elif echo "$detected_gpu" | grep -iqE "mali|meow"; then GPU_NAME="mali" elif echo "$detected_gpu" | grep -iqE "xclipse|samsung"; then GPU_NAME="xclipse" else GPU_NAME="unknown" fi } function check_system_requirements() { while true; do local errors=0 clear # Disable keyboard interruptions trap '' SIGINT SIGTSTP printf "%s############################################################\n" "$C" printf "%s# #\n" "$C" printf "%s# ▀█▀ █▀▀ █▀█ █▀▄▀█ █ █ ▀▄▀   █▀▄ █▀▀ █▀ █▄▀ ▀█▀ █▀█ █▀█ #\n" "$C" printf "%s# █  ██▄ █▀▄ █ █ █▄█ █ █   █▄▀ ██▄ ▄█ █ █  █  █▄█ █▀▀ #\n" "$C" printf "%s# #\n" "$C" printf "%s################# System Compatibility Check ###############%s\n" "$C" "$NC" echo " " sleep 0.3 # Check if running on Android ANDROID_VERSION=$(getprop ro.build.version.release | cut -d'.' -f1) if [[ "$(uname -o)" == "Android" ]]; then if [[ "$ANDROID_VERSION" -ge 8 ]]; then print_success "Running on: ${NC}Android $ANDROID_VERSION" else print_failed "Running on: ${NC}Android $ANDROID_VERSION is not recomended" ((errors++)) fi else print_failed "Not running on Android" ((errors++)) fi sleep 0.2 # Android device soc & model details MODEL="$(getprop ro.product.brand) $(getprop ro.product.model)" print_success "Device: ${NC}$MODEL" sleep 0.2 PROCESSOR_BRAND_NAME="$(getprop ro.soc.manufacturer)" PROCESSOR_NAME="$(getprop ro.soc.model)" HARDWARE="$(getprop ro.hardware)" if [[ -n "$PROCESSOR_BRAND_NAME" && -n "$PROCESSOR_NAME" ]]; then print_success "SOC: ${NC}$PROCESSOR_BRAND_NAME $PROCESSOR_NAME" else print_success "SOC: ${NC}$HARDWARE" fi sleep 0.2 # Check GPU try_to_autodetect_gpu if [[ "$GPU_NAME" == "adreno" ]] || [[ "$GPU_NAME" == "mali" ]] || [[ "$GPU_NAME" == "xclipse" ]]; then print_success "GPU: ${NC}$GPU_NAME" else print_warn "Unknown GPU: ${NC}$GPU_NAME" fi sleep 0.2 # Check architecture if [[ "$termux_arch" == "aarch64" ]] || [[ "$termux_arch" == "arm" ]]; then print_success "App architecture: ${NC}$APP_ARCH" else print_failed "Unsupported architecture: $APP_ARCH, requires aarch64/arm/armv7*/armv8*" ((errors++)) fi sleep 0.2 # Check for termux app requirements if [[ -d "$PREFIX" ]]; then print_success "Termux PREFIX: ${NC}Directory found" sleep 0.2 local latest_termux_app_tag latest_termux_app_tag=$(get_latest_release "termux" "termux-app") if [[ "$TERMUX_VERSION" == "${latest_termux_app_tag#v}" ]]; then print_success "Termux Version: ${NC}$TERMUX_VERSION" sleep 0.2 local termux_build termux_build=$(echo "$TERMUX_APK_RELEASE" | awk '{print tolower($0)}') if [[ "$termux_build" == "github" ]] || [[ "$termux_build" == "fdroid" ]]; then print_success "Termux Build: ${NC}$TERMUX_APK_RELEASE" sleep 0.2 else print_failed "$TERMUX_APK_RELEASE build is not recomended" echo "${NC} Update Termux:- https://github.com/termux/termux-app/releases ${NC}" sleep 0.2 fi else print_warn "Termux Version: ${NC}$TERMUX_VERSION (Not Recomended)" if [[ $(getprop ro.product.cpu.abi) == "arm64-v8a" ]]; then echo "${R}[${G}!${R}]${G} Update Termux:- https://github.com/termux/termux-app/releases/download/${latest_termux_app_tag}/termux-app_${latest_termux_app_tag}+github-debug_arm64-v8a.apk${NC}" elif [[ $(getprop ro.product.cpu.abi) == "armeabi-v7a" ]]; then echo "${R}[${G}!${R}]${G} Update Termux:- https://github.com/termux/termux-app/releases/download/${latest_termux_app_tag}/termux-app_${latest_termux_app_tag}+github-debug_armeabi-v7a.apk${NC}" else echo "${R}[${G}!${R}]${G} Update Termux:- https://github.com/termux/termux-app/releases/download/${latest_termux_app_tag}/termux-app_${latest_termux_app_tag}+github-debug_universal.apk${NC}" fi sleep 0.2 fi else print_failed "Termux PREFIX: directory not found" ((errors++)) sleep 0.2 fi # Check available storage space FREE_SPACE=$(df -h "$HOME" | awk 'NR==2 {print $4}') if [[ $(df "$HOME" | awk 'NR==2 {print $4}') -gt 4194304 ]]; then print_success "Available storage: ${NC}$FREE_SPACE" else print_warn "Low storage space: ${NC}$FREE_SPACE (4GB recommended)" fi sleep 0.2 # Check RAM TOTAL_RAM=$(free -htm | awk '/Mem:/ {print $2}') if [[ $(free -m | awk 'NR==2 {print $2}') -gt 2048 ]]; then print_success "RAM: ${NC}${TOTAL_RAM}" else print_warn "Low RAM: ${NC}${TOTAL_RAM} (2GB recommended)" fi sleep 0.2 # Check termux x11 if cmd package list packages --user 0 -e -f | sed 's/package://; s/\.apk=/\.apk /' | grep -q "com.termux.x11"; then print_success "Termux-x11: ${NC}Installed" else local latest_termux_x11_tag latest_termux_x11_tag=$(get_latest_release "termux" "termux-x11") print_failed "Termux-x11: ${NC}Not Installed" if [[ $(getprop ro.product.cpu.abi) == "arm64-v8a" ]]; then print_msg "${BOLD}Install Termux-x11:- ${NC}https://github.com/termux/termux-x11/releases/download/${latest_termux_x11_tag}/app-arm64-v8a-debug.apk" elif [[ $(getprop ro.product.cpu.abi) == "armeabi-v7a" ]]; then print_msg "${BOLD}Install Termux-x11:- ${NC}https://github.com/termux/termux-x11/releases/download/${latest_termux_x11_tag}/app-armeabi-v7a-debug.apk" else print_msg "${BOLD}Install Termux-x11:- ${NC}https://github.com/termux/termux-x11/releases/download/${latest_termux_x11_tag}/app-universal-debug.apk" fi ((errors++)) fi # Check termux API if cmd package list packages --user 0 -e -f | sed 's/package://; s/\.apk=/\.apk /' | grep -q "com.termux.api"; then IS_TERMUX_API_INSTALLED=true print_success "Termux-API: ${NC}Installed" else local latest_termux_api_tag latest_termux_api_tag=$(get_latest_release "termux" "termux-api") print_failed "Termux-API: ${NC}Not Installed" print_msg "${BOLD}Install Termux-API:- ${NC}https://github.com/termux/termux-api/releases/download/${latest_termux_api_tag}/termux-api-app_${latest_termux_api_tag}+github-debug.apk" ((errors++)) fi echo " " if [[ $errors -eq 0 ]]; then print_success "All system requirements met!" sleep 0.2 return 0 else while true; do print_failed "Found $errors error(s). System requirements not met." sleep 0.2 print_msg "Type 'a' to check again" read -r -p "${R}[${C}-${R}]${Y}${BOLD} Do you want to continue anyway (Not Recomended) ${Y}(y/n/a) ${NC}" sys_requirements_check case $sys_requirements_check in [yY]*) echo print_success "Continuing aniway..." echo sleep 0.2 break 2 ;; [aA]*) echo print_success "Starting check again..." echo sleep 0.2 break ;; [nN]*) trap - SIGINT SIGTSTP exit 1 ;; *) echo print_failed "Invalid input. Please enter 'y' / 'n' / 'a'." echo ;; esac done log_debug "System requirements not met $sys_requirements_check" fi done } function print_recomended_msg() { check_system_requirements echo print_msg "${BOLD}Pre-Installation Requirements" echo echo "${G}Essential Steps:${NC}" echo " • Start with a clean installation" echo " • Ensure at least 1GB of available data" echo " • Use a stable internet connection or VPN" echo echo "${G}Device Settings:${NC}" echo " • Enable 'Keep screen on' in Termux settings" if [[ "$ANDROID_VERSION" -ge 12 ]]; then echo " • Disable Phantom Process Killer (Android 12+ requirement)" fi echo echo "${G}Important Notes:${NC}" echo " • Keep Termux open during the entire installation" echo " • Review all README documentation carefully" echo " • In the multi selection option press enter to go with the default option" echo # Re-enable keyboard interruptions trap - SIGINT SIGTSTP wait_for_keypress } function install_required_packages() { banner print_msg "${BOLD}Installing required packages..." echo if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then package_install_and_check "wget git jq curl tar xz-utils gzip libpopt termux-am termux-api" else package_install_and_check "wget git jq curl tar xz-utils gzip libpopt termux-am x11-repo tur-repo termux-api" fi } function recheck_basic_packages() { print_msg "${BOLD}Checking required packages..." local max_retries=3 local retry_count=0 local basic_packages=("wget" "git" "jq" "curl" "tar" "tar" "gzip" "termux-am" "termux-api-start") local pack while [[ "$retry_count" -le "$max_retries" ]]; do local missing_packages=() for pack in "${basic_packages[@]}"; do print_msg "Checking command $pack" if ! command -v "$pack" >/dev/null 2>&1; then missing_packages+=("$pack") fi done [[ ${#missing_packages[@]} -eq 0 ]] && return 0 ((retry_count++)) print_msg "Attempt $retry_count: Installing missing packages..." print_msg "Missing packages: ${missing_packages[*]}" install_required_packages done print_failed "Error: Failed to install packages after 3 attempts" print_failed "Missing packages: ${missing_packages[*]}" exit 1 } function install_desktop() { log_debug "Starting desktop installation" "Desktop: $de_name" banner if [[ "$de_name" == "xfce" ]]; then print_msg "${BOLD}Installing Xfce4 Desktop" package_install_and_check "xfce4 xfce4-goodies xfce4-pulseaudio-plugin xfce4-battery-plugin xfce4-docklike-plugin xfce4-notifyd-static xfce4-cpugraph-plugin kvantum" elif [[ "$de_name" == "lxqt" ]]; then print_msg "${BOLD}Installing Lxqt Desktop" echo package_install_and_check "lxqt openbox gtk3 papirus-icon-theme xorg-xsetroot kvantum" elif [[ "$de_name" == "openbox" ]]; then print_msg "${BOLD}Installing Openbox WM" echo package_install_and_check "openbox polybar xorg-xsetroot xorg-xprop lxappearance wmctrl feh firefox rofi bmon xcompmgr gtk3 gedit xmllint kvantum" elif [[ "$de_name" == "mate" ]]; then print_msg "${BOLD}Installing MATE" echo package_install_and_check "mate*" package_install_and_check "marco mousepad xfce4-taskmanager eog kvantum" elif [[ "$de_name" == "i3wm" ]]; then print_msg "${BOLD}Installing i3WM" package_install_and_check "i3" elif [[ "$de_name" == "dwm" ]]; then print_msg "${BOLD}Installing DWM" package_install_and_check "dwm" elif [[ "$de_name" == "bspwm" ]]; then print_msg "${BOLD}Installing BSPWM" package_install_and_check "bspwm lxappearance xorg-xsetroot rofi feh" elif [[ "$de_name" == "awesome" ]]; then print_msg "${BOLD}Installing AWESOME WM" package_install_and_check "awesome" elif [[ "$de_name" == "fluxbox" ]]; then print_msg "${BOLD}Installing Fluxbox WM" echo package_install_and_check "fluxbox xorg-xsetroot xorg-xprop lxappearance wmctrl feh firefox rofi bmon xcompmgr gtk3 gedit xmllint" elif [[ "$de_name" == "icewm" ]]; then print_msg "${BOLD}Installing Ice WM" echo package_install_and_check "icewm" package_install_and_check "xdg-menu" elif [[ "$de_name" == "gnome" ]]; then print_msg "${BOLD}Installing Gnome" echo mkdir gnome_packages_files cd gnome_packages_files || exit 1 if [[ "$PACKAGE_MANAGER" == "apt" ]]; then download_and_extract "https://github.com/sabamdarif/termux-desktop/releases/download/gnome-shell/debs-${termux_arch}.zip" download_file "https://github.com/sabamdarif/Termux-AppStore/releases/download/files/refine_0.5.10_${termux_arch}.deb" dpkg --configure -a apt --fix-broken install -y apt install ./*deb -y apt install --fix-missing -y elif [[ "$PACKAGE_MANAGER" == "pacman" ]]; then download_and_extract "https://github.com/sabamdarif/termux-desktop/releases/download/gnome-shell/pkgs-${termux_arch}.zip" download_file "https://github.com/sabamdarif/Termux-AppStore/releases/download/files/refine_0.5.10_${termux_arch}.pkg.tar.xz" pacman -U --noconfirm ./*.pkg.tar.xz else print_failed "Unsupported package manger, you need APT / PACMAN" exit 1 fi cd .. check_and_delete "gnome_packages_files" package_install_and_check "xfce4-terminal eog" elif [[ "$de_name" == "cinnamon" ]]; then print_msg "${BOLD}Installing Cinnamon" echo package_install_and_check "cinnamon nemo gnome-terminal gnome-screenshot eog" fi if [[ "$LITE_MODE" != "1" && "$LITE_MODE" != "true" ]]; then package_install_and_check "file-roller pavucontrol gnome-font-viewer evince galculator xorg-xrdb" fi # Uncomment if additional package installation is needed # if [[ "$distro_add_answer" == "y" ]]; then # package_install_and_check "xdg-utils" # fi print_to_config "de_startup" print_to_config "de_name" print_to_config "themes_folder" print_to_config "icons_folder" log_debug "Desktop installation process done" } function ext_setup_for_stock() { if [[ "$de_name" == "icewm" ]]; then print_msg "Genarating a simple menu for icewm..." check_and_backup "$HOME/.icewm" check_and_create_directory "$HOME/.icewm" xdg_menu --format icewm --fullmenu --root-menu "$PREFIX/etc/xdg/menus/termux-applications.menu" >~/.icewm/programs fi } ######################################################################### # # Theme Installer # ######################################################################### function set_config_dir() { if [[ "$de_name" == "xfce" ]]; then config_dirs=(autostart cairo-dock eww picom dconf gtk-3.0 Mousepad pulse Thunar menu ristretto rofi xfce4) elif [[ "$de_name" == "lxqt" ]]; then config_dirs=(fontconfig gtk-3.0 lxqt pcmanfm-qt QtProject.conf glib-2.0 Kvantum openbox qterminal.org) elif [[ "$de_name" == "mate" ]]; then config_dirs=(caja dconf galculator gtk-3.0 Kvantum lximage-qt menus Mousepad pavucontrol.ini xfce4) else config_dirs=(dconf gedit Kvantum openbox pulse rofi xfce4 enchant gtk-3.0 mimeapps.list polybar QtProject.conf Thunar) fi } function ext_wall_setup() { banner if [[ "$ext_wall_answer" == "n" ]]; then print_msg "${C}Skipping Extra Wallpapers Setup..." echo elif [[ "$ext_wall_answer" == "y" ]]; then # if we doesn't set this to only run when CALL_FROM_CHANGE_STYLE == false then it will clone the wallpapers each time user run --change style if [[ "$CALL_FROM_CHANGE_STYLE" == false ]]; then print_msg "${BOLD}Installing Some Extra Wallpapers..." echo check_and_create_directory "$PREFIX/share/backgrounds" # download_and_extract "https://archive.org/download/wallpaper-extra.tar/wallpaper-extra.tar.gz" "$PREFIX/share/backgrounds/" cd "${HOME}" || exit 1 git clone --recursive --depth=1 -j "$(nproc)" https://github.com/JaKooLit/Wallpaper-Bank cd Wallpaper-Bank/wallpapers/ || exit 1 mv Dynamic-Wallpapers/* "$PREFIX/share/backgrounds/" check_and_delete "Dynamic-Wallpapers" mv ./* "$PREFIX/share/backgrounds/" cd "${HOME}" || exit 1 check_and_delete "Wallpaper-Bank" fi fi print_to_config "ext_wall_answer" } function theme_installer() { log_debug "Starting theme installation" "Theme: $style_name" banner print_msg "${BOLD}Configuring Theme: ${C}${style_name}" echo package_install_and_check "gnome-themes-extra gtk2-engines-murrine" sleep 3 banner print_msg "${BOLD}Configuring Wallpapers..." echo check_and_create_directory "$PREFIX/share/backgrounds" download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/wallpaper.tar.gz" "$PREFIX/share/backgrounds/" banner print_msg "${BOLD}Configuring Icon Pack..." echo package_install_and_check "gdk-pixbuf" if [[ -z "$icons_folder" ]]; then icons_folder="$HOME/.icons" fi check_and_create_directory "$icons_folder" download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/icon.tar.gz" "$icons_folder" if [[ "$de_name" == "xfce" ]]; then local icons_themes_names icons_themes_names=$(ls "$icons_folder") local icons_theme for icons_theme in $icons_themes_names; do if [[ -d "$icons_folder/$icons_theme" ]]; then print_msg "Creating icon cache..." gtk-update-icon-cache -f -t "$icons_folder/$icons_theme" fi done fi local sys_icons_themes_names sys_icons_themes_names=$(ls "$PREFIX/share/icons") local sys_icons_theme for sys_icons_theme in $sys_icons_themes_names; do if [[ -d "$sys_icons_folder/$sys_icons_theme" ]]; then print_msg "Creating icon cache..." gtk-update-icon-cache -f -t "$sys_icons_folder/$sys_icons_theme" fi done print_msg "${BOLD}Installing Theme..." echo if [[ -z "$themes_folder" ]]; then themes_folder="$HOME/.themes" fi check_and_create_directory "$themes_folder" download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/theme.tar.gz" "$themes_folder" if [[ -d "$HOME/.config" ]] || [[ -d "$HOME/.local" ]]; then print_msg "Creating backup of old config..." must_back_folders=("$HOME/.config") if [[ -d "$HOME/.local" ]]; then must_back_folders+=("$HOME/.local") fi tar -cJvf "$HOME/old-config-$(date +%Y%m%d-%H%M%S).tar.xz" --warning=no-file-removed "${must_back_folders[@]}" fi print_msg "Applying Custom Configuration..." echo check_and_create_directory "$HOME/.config" set_config_dir for the_config_dir in "${config_dirs[@]}"; do check_and_delete "$HOME/.config/$the_config_dir" done if [[ "$de_name" == "openbox" ]]; then download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/config.tar.gz" "$HOME" else download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/config.tar.gz" "$HOME/.config/" fi } ######################################################################### # # Install Additional Packages For Setup # ######################################################################### function additional_required_steps() { banner if [[ "$de_name" == "xfce" ]]; then print_msg "${BOLD} Installing Additional Packages If Required...${NC}" echo if [[ "$style_answer" == "4" ]] || [[ "$style_answer" == "5" ]]; then install_font_for_style "${style_answer}" fi if [[ "$style_answer" == "5" ]] || [[ "$style_answer" == "6" ]]; then package_install_and_check "eww" fi if [[ "$style_answer" == "6" ]]; then package_install_and_check "rofi" fi if [[ "$style_answer" == "3" ]]; then package_install_and_check "xdotool" fi elif [[ "$de_name" == "openbox" ]]; then if [[ "$style_answer" == "1" ]]; then package_install_and_check "xfce4-settings mpd thunar" install_font_for_style "1" elif [[ "$style_answer" == "2" ]]; then package_install_and_check "devilspie2 xfce4-terminal thunar dunst python python3 tint2 xdotool" install_font_for_style "2" print_msg "${BOLD}Installing package: ${C}pywal" pip install pywal print_msg "${BOLD}Installing package: ${C}pyyaml" pip install pyyaml print_msg "${BOLD}Installing package: ${C}pyxdg" pip install pyxdg print_msg "${BOLD}Installing package: ${C}docopt" pip install docopt print_msg "${BOLD}Installing package: ${C}rofimoji" pip install rofimoji fi fi } ######################################################################### # # Setup Selected Style And Wallpapers / setup config # ######################################################################### function setup_config() { cd "$HOME" || return if [[ ${style_answer} =~ ^[1-9][0-9]*$ ]]; then banner print_msg "${BOLD}Installing $de_name Style: ${C}${style_answer}" theme_installer additional_required_steps print_to_config "style_answer" else print_failed "Failed to select style..." fi } ######################################################################### # # Setup required permissions # ######################################################################### function setup_folder() { banner print_msg "${BOLD}Configuring Storage..." echo while true; do termux-setup-storage sleep 4 if [[ -d ~/storage ]]; then print_success "Storage configured successfully" break else print_failed "Storage permission denied" fi sleep 3 done cd "$HOME" || return termux-reload-settings directories=(Music Pictures Videos) for dir in "${directories[@]}"; do check_and_create_directory "/sdcard/$dir" done check_and_create_directory "$HOME/Desktop" ln -s "$HOME/storage/shared/Music" "$HOME/" ln -s "$HOME/storage/shared/Pictures" "$HOME/" ln -s "$HOME/storage/shared/Videos" "$HOME/" } function setup_mic_permission() { if [[ "$IS_TERMUX_API_INSTALLED" == true ]]; then print_msg "Setting up mic permission..." echo print_msg "Please grant mic permission" echo sleep 2 termux-microphone-record -l 1 -f /dev/null >/dev/null 2>&1 & sleep 5 else print_msg "You can't use microphone because you didn't install Termux-Api apk" sleep 3 fi } function setup_necessary_permissions() { setup_folder setup_mic_permission } ######################################################################### # # Hardware Acceleration Setup # ######################################################################### # setup hardware acceleration, check if the enable-hw-acceleration already exist, if then first check if it different from github , then ask user if they want to replace it with the latest or not, if not then continue with the local enable-hw-acceleration file function get_hw_acceleration_source() { local script_path="${current_path}/enable-hw-acceleration" local remote_url="https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/enable-hw-acceleration" if [[ -f "$script_path" ]]; then local current_script_hash current_script_hash=$(curl -sL "$remote_url" | sha256sum | cut -d ' ' -f 1) # Add error checking for remote fetch if [[ -z "$current_script_hash" ]]; then print_msg "Failed to fetch remote script for comparison. Using local version." chmod +x "$script_path" return fi local local_script_hash local_script_hash=$(sha256sum "$script_path" | cut -d ' ' -f 1) if [[ "$local_script_hash" != "$current_script_hash" ]]; then print_msg "A different version of the hardware acceleration installer is detected." echo confirmation_y_or_n "Do you want to replace it with the latest version?" change_old_hw_installer if [[ "$change_old_hw_installer" == "y" ]]; then check_and_backup "$script_path" download_file "$script_path" "$remote_url" else print_msg "Using the local hardware acceleration setup file." fi print_to_config "change_old_hw_installer" else print_msg "Using the local hardware acceleration setup file." fi else download_file "$script_path" "$remote_url" fi chmod +x "$script_path" } function hw_config() { banner print_msg "${BOLD}Configuring Hardware Acceleration" echo print_to_config "enable_hw_acc" # Get the hardware acceleration source get_hw_acceleration_source # Source the script # shellcheck disable=SC1091 source "${current_path}/enable-hw-acceleration" # Call the main hardware acceleration setup function run_hw_acceleration_setup_main # Clean up check_and_delete "${current_path}/enable-hw-acceleration" log_debug "$current_path $current_script_hash $local_script_hash" } ######################################################################### # # Proot Distro Setup # ######################################################################### # same as the hardware acceleration setup but for distro-container-setup file function get_distro_container_source() { local script_path="${current_path}/distro-container-setup" local remote_url="https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/distro-container-setup" if [[ -f "$script_path" ]]; then local current_script_hash current_script_hash=$(curl -sL "$remote_url" | sha256sum | cut -d ' ' -f 1) local local_script_hash local_script_hash=$(sha256sum "$script_path" | cut -d ' ' -f 1) if [[ "$local_script_hash" != "$current_script_hash" ]]; then print_msg "It looks like you already have a different distro-container setup script in your current directory" echo confirmation_y_or_n "Do you want to change it with the latest installer" change_old_distro_installer if [[ "$change_old_distro_installer" == "y" ]]; then check_and_backup "$script_path" download_file "$script_path" "$remote_url" else print_msg "Using the local distro-container setup file" fi print_to_config "change_old_distro_installer" else print_msg "Using the local distro-container setup file" fi else download_file "$script_path" "$remote_url" fi chmod +x "$script_path" } function distro_container_setup() { print_to_config "distro_add_answer" if [[ "$distro_add_answer" == "n" ]]; then banner print_msg "${C}Skipping Linux Distro Container Setup..." echo if [[ "$enable_hw_acc" == "y" ]]; then hw_config else print_to_config "enable_hw_acc" fi else banner print_msg "${BOLD}Configuring Linux Distro Container" echo # Get the distro container source get_distro_container_source # Source the script # shellcheck disable=SC1091 source "${current_path}/distro-container-setup" # Call the main distro container setup function run_distro_container_setup_main # Clean up check_and_delete "${current_path}/distro-container-setup" fi log_debug "$current_path $distro_add_answer $local_script_hash" } ######################################################################### # # Vnc | Termux:x11 | Launch Scripts # ######################################################################### function setup_vncstart_cmd() { check_and_delete "$PREFIX/bin/vncstart" if [[ "$enable_hw_acc" == "n" ]]; then cat <"$PREFIX/bin/vncstart" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=\$(grep TracerPid "/proc/\$\$/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_PID" != 0 ]; then TRACER_NAME=\$(grep Name "/proc/\${TRACER_PID}/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_NAME" = "proot" ]; then msg print_failed "vncstart command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID termux-wake-lock # Prevent script from looping by checking if it's already running if [[ "\$1" != "--help" && "\$1" != "-h" ]]; then if pgrep -f "vncserver" >/dev/null; then echo "[!] vncserver is already running. Exiting." exit 1 fi fi vnc_server_pid=\$(pgrep -f "vncserver") de_pid=\$(pgrep -f "$de_startup") if [[ -n "\$de_pid" || -n "\$vnc_server_pid" ]]; then vncstop -f fi if [[ "\$1" != "--help" && "\$1" != "-h" ]]; then if \$use_debug; then rm -rf ~/.config/pulse/*-runtime/pid else rm -rf ~/.config/pulse/*-runtime/pid >/dev/null 2>&1 fi pulseaudio --start --exit-idle-time=-1 pactl load-module module-sles-source > /dev/null 2>&1 fi function show_vncstart_help() { echo -e "\nUsage:\n" echo "vncstart to start vncserver" echo "vncstart --help to show help" } case \$1 in --help|-h) show_vncstart_help ;; *) if [[ -n "\$1" ]]; then echo "[☓] Invalid option: \$1" show_vncstart_help else env XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg vncserver fi ;; esac EOF elif [[ "$enable_hw_acc" == "y" ]]; then cat <"$PREFIX/bin/vncstart" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=\$(grep TracerPid "/proc/\$\$/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_PID" != 0 ]; then TRACER_NAME=\$(grep Name "/proc/\${TRACER_PID}/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_NAME" = "proot" ]; then msg print_failed "vncstart command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID termux-wake-lock # Prevent script from looping by checking if it's already running if [[ "\$1" != "--help" && "\$1" != "-h" ]]; then if pgrep -f "vncserver" >/dev/null; then echo "[!] vncserver is already running. Exiting." exit 1 fi fi vnc_server_pid=\$(pgrep -f "vncserver") de_pid=\$(pgrep -f "$de_startup") if [[ -n "\$de_pid" || -n "\$vnc_server_pid" ]]; then vncstop -f fi if [[ "\$1" != "--help" && "\$1" != "-h" ]]; then if \$use_debug; then rm -rf ~/.config/pulse/*-runtime/pid else rm -rf ~/.config/pulse/*-runtime/pid >/dev/null 2>&1 fi pulseaudio --start --exit-idle-time=-1 pactl load-module module-sles-source > /dev/null 2>&1 fi function show_vncstart_help() { echo -e "\nUsage:\n" echo "vncstart to start vncserver with GPU acceleration" echo "vncstart --nogpu to start vncserver without GPU acceleration" echo "vncstart --help to show this help message" } case \$1 in --nogpu) env XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg LIBGL_ALWAYS_SOFTWARE=1 MESA_LOADER_DRIVER_OVERRIDE=llvmpipe GALLIUM_DRIVER=llvmpipe vncserver ;; --help|-h) show_vncstart_help ;; *) if [[ -n "\$1" ]]; then echo "[☓] Invalid option: \$1" show_vncstart_help else export ${set_to_export} ${initialize_server_method} & env XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg $hw_method vncserver fi ;; esac EOF fi chmod +x "$PREFIX/bin/vncstart" } function setup_vncstop_cmd() { check_and_delete "$PREFIX/bin/vncstop" cat <<'EOF' >"$PREFIX/bin/vncstop" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=$(grep TracerPid "/proc/$$/status" | cut -d $'\t' -f 2) if [ "$TRACER_PID" != 0 ]; then TRACER_NAME=$(grep Name "/proc/${TRACER_PID}/status" | cut -d $'\t' -f 2) if [ "$TRACER_NAME" = "proot" ]; then msg print_failed "vncstop command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID termux-wake-unlock if [[ "$1" == "-f" ]] || [[ "$1" == "--force" ]]; then pkill -9 Xtigervnc > /dev/null 2>&1 elif [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then echo -e " vncstop to stop vncserver vncstop --force to force stop vncserver vncstop --help to show the helps " else display_numbers=$(vncserver -list | awk '/^:[0-9]+/ {print $1}') for display in $display_numbers; do vncserver -kill "$display" done fi rm $HOME/.vnc/localhost:*.log > /dev/null 2>&1 rm $PREFIX/tmp/.X1-lock > /dev/null 2>&1 rm $PREFIX/tmp/.X11-unix/X1 > /dev/null 2>&1 EOF chmod +x "$PREFIX/bin/vncstop" } function setup_vnc() { banner print_msg "${BOLD}Configuring Vnc..." echo package_install_and_check "tigervnc" check_and_create_directory "$HOME/.vnc" check_and_delete "$HOME/.vnc/xstartup" cat <"$HOME/.vnc/xstartup" $de_startup & EOF chmod +x "$HOME/.vnc/xstartup" setup_vncstart_cmd setup_vncstop_cmd } function setup_tx11start_cmd() { check_and_delete "$PREFIX/bin/tx11start" if [[ "$enable_hw_acc" == "y" ]]; then cat <"$PREFIX/bin/tx11start" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=\$(grep TracerPid "/proc/\$\$/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_PID" != 0 ]; then TRACER_NAME=\$(grep Name "/proc/\${TRACER_PID}/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_NAME" = "proot" ]; then msg print_failed "tx11start command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID # Initialize flags use_nogpu=false use_nodbus=false use_legacy=false use_debug=false de_startup="$de_startup" # Function to show help function show_tx11start_help() { echo -e " tx11start - Start Termux:X11 with GPU acceleration tx11start --nogpu - Start without GPU acceleration tx11start --nodbus - Start without dbus tx11start --legacy - Start with -legacy-drawing tx11start --debug - Show debug log tx11start --xstartup "xstartup-name" - Launch another desktop environment " exit 0 } # Parse arguments while ((\$# >= 1)); do case "\$1" in --help) show_tx11start_help ;; --xstartup | -xstartup) shift de_startup="\$1" echo "\$de_startup" > "$HOME/.xstartup" ;; --nogpu | --no-gpu) use_nogpu=true ;; --nodbus | --no-dbus) use_nodbus=true ;; --legacy) use_legacy=true ;; --debug) use_debug=true ;; *) echo "Invalid option: \$1" show_tx11start_help ;; esac shift done # Kill existing Termux X11 processes pkill -f com.termux.x11 >/dev/null 2>&1 pkill -9 "\$de_startup" >/dev/null 2>&1 # Ensure XDG_RUNTIME_DIR exists export XDG_RUNTIME_DIR=/data/data/com.termux/files/usr/tmp mkdir -p "\$XDG_RUNTIME_DIR" # Export DISPLAY variable export DISPLAY=:${display_number} # Start pulseaudio unless --help was given if [[ "\$1" != "--help" ]]; then termux-wake-lock if \$use_debug; then rm -rf ~/.config/pulse/*-runtime/pid else rm -rf ~/.config/pulse/*-runtime/pid >/dev/null 2>&1 fi # pulseaudio --start --load="module-aaudio-sink" --exit-idle-time=-1 pulseaudio --start --exit-idle-time=-1 pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1 if \$use_debug; then pactl load-module module-sles-source else pactl load-module module-sles-source >/dev/null 2>&1 fi fi # Set environment variables if NOT using --nogpu if ! \$use_nogpu; then export ${set_to_export} if \$use_debug; then ${initialize_server_method} & else ${initialize_server_method} >/dev/null 2>&1 & fi export ${gpu_environment_variable} ${hw_method} else export LIBGL_ALWAYS_SOFTWARE=1 MESA_LOADER_DRIVER_OVERRIDE=llvmpipe GALLIUM_DRIVER=llvmpipe fi sleep 1 # Construct X11 command # x11_cmd="XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR} termux-x11 :0" # Comment this because i found that the sound doesn't working if i set this XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR} if \$use_nogpu; then x11_cmd="LIBGL_ALWAYS_SOFTWARE=1 termux-x11 :0" else x11_cmd="termux-x11 :0" fi if \$use_legacy; then x11_cmd+=" -legacy-drawing" fi # Start X11 if \$use_debug; then eval "\$x11_cmd" & else eval "\$x11_cmd" >/dev/null 2>&1 & fi sleep 1 # Start X11 Main Activity if \$use_debug; then am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity else am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity >/dev/null 2>&1 fi sleep 1 # Start the desktop environment if \$use_nodbus; then if \$use_debug; then env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg \$de_startup & else env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg \$de_startup >/dev/null 2>&1 & fi else if \$use_debug; then env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg dbus-launch --exit-with-session \$de_startup & else env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg dbus-launch --exit-with-session \$de_startup >/dev/null 2>&1 & fi fi EOF elif [[ "$enable_hw_acc" == "n" ]]; then cat <"$PREFIX/bin/tx11start" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=\$(grep TracerPid "/proc/\$\$/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_PID" != 0 ]; then TRACER_NAME=\$(grep Name "/proc/\${TRACER_PID}/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_NAME" = "proot" ]; then msg print_failed "tx11start command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID # Initialize flags use_nodbus=false use_legacy=false use_debug=false de_startup="$de_startup" # Function to show help function show_tx11start_help() { echo -e " tx11start - Start Termux:X11 tx11start --nodbus - Start without dbus tx11start --legacy - Start with -legacy-drawing tx11start --debug - Show debug log tx11start --xstartup "xstartup-name" - Launch another desktop environment " exit 0 } # Parse arguments while ((\$# >= 1)); do case "\$1" in --help) show_tx11start_help ;; --xstartup | -xstartup) shift de_startup="\$1" echo "\$de_startup" > "$HOME/.xstartup" ;; --nodbus | --no-dbus) use_nodbus=true ;; --legacy) use_legacy=true ;; --debug) use_debug=true ;; *) echo "Invalid option: \$1" show_tx11start_help ;; esac shift done # Kill existing Termux X11 processes pkill -f com.termux.x11 >/dev/null 2>&1 pkill -9 "\$de_startup" >/dev/null 2>&1 # Ensure XDG_RUNTIME_DIR exists export XDG_RUNTIME_DIR=/data/data/com.termux/files/usr/tmp mkdir -p "\$XDG_RUNTIME_DIR" # Export DISPLAY variable export DISPLAY=:${display_number} # Start pulseaudio unless --help was given if [[ "\$1" != "--help" ]]; then termux-wake-lock if \$use_debug; then rm -rf ~/.config/pulse/*-runtime/pid else rm -rf ~/.config/pulse/*-runtime/pid >/dev/null 2>&1 fi # pulseaudio --start --load="module-aaudio-sink" --exit-idle-time=-1 pulseaudio --start --exit-idle-time=-1 pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1 if \$use_debug; then pactl load-module module-sles-source else pactl load-module module-sles-source >/dev/null 2>&1 fi fi # Construct X11 command # x11_cmd="XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR} termux-x11 :0" # Comment this because i found that the sound doesn't working if i set this XDG_RUNTIME_DIR=\${XDG_RUNTIME_DIR} x11_cmd="termux-x11 :0" if \$use_legacy; then x11_cmd+=" -legacy-drawing" fi # Start X11 if \$use_debug; then eval "\$x11_cmd" & else eval "\$x11_cmd" >/dev/null 2>&1 & fi sleep 1 # Start X11 Main Activity if \$use_debug; then am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity else am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity >/dev/null 2>&1 fi sleep 1 # Start the desktop environment if \$use_nodbus; then if \$use_debug; then env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg \$de_startup & else env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg \$de_startup >/dev/null 2>&1 & fi else if \$use_debug; then env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg dbus-launch --exit-with-session \$de_startup & else env DISPLAY=:${display_number} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg dbus-launch --exit-with-session \$de_startup >/dev/null 2>&1 & fi fi EOF fi if [[ "$de_name" == "xfce" ]]; then cat <>"$PREFIX/bin/tx11start" # Kill xfce4-screensaver if running sleep 5 process_id=\$(ps aux | grep '[x]fce4-screensaver' | awk '{print \$2}') if [[ -n "\$process_id" ]]; then if \$use_debug; then kill "\$process_id" else kill "\$process_id" > /dev/null 2>&1 fi fi EOF fi chmod +x "$PREFIX/bin/tx11start" } function setup_tx11stop_cmd() { check_and_delete "$PREFIX/bin/tx11stop" if [[ "$de_name" == "openbox" ]]; then cat <"$PREFIX/bin/tx11stop" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=\$(grep TracerPid "/proc/\$\$/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_PID" != 0 ]; then TRACER_NAME=\$(grep Name "/proc/\${TRACER_PID}/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_NAME" = "proot" ]; then msg print_failed "tx11stop command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID termux-wake-unlock if [[ -f "$HOME/.xstartup" ]]; then de_startup=\$(cat "$HOME/.xstartup") else de_startup="$de_startup" fi termux_x11_pid=\$(pgrep -f "/system/bin/app_process / com.termux.x11.Loader :${display_number}") de_pid=\$(pgrep -f \$de_startup) if [[ -n "\$termux_x11_pid" ]] || [[ -n "\$de_pid" ]]; then kill -9 "\$termux_x11_pid" > /dev/null 2>&1 pkill -9 pulseaudio > /dev/null 2>&1 killall virgl_test_server > /dev/null 2>&1 pkill -9 openbox* > /dev/null 2>&1 pkill -9 dbus-* > /dev/null 2>&1 pkill -f com.termux.x11 > /dev/null 2>&1 sleep 1 if [[ ! -n "\$termux_x11_pid" ]] || [[ ! -n "\$de_pid" ]]; then echo -e "${G}Termux:X11 Stopped Successfully ${NC}" [[ -f "$HOME/.xstartup" ]] && rm -rf "$HOME/.xstartup" fi elif [[ "\$1" == "-f" ]] || [[ "\$1" == "--force" ]]; then pkill -f com.termux.x11 > /dev/null 2>&1 pkill -9 openbox* > /dev/null 2>&1 killall virgl_test_server > /dev/null 2>&1 pkill -9 pulseaudio > /dev/null 2>&1 pkill -9 dbus-* > /dev/null 2>&1 echo -e "${G}Termux:X11 Successfully Force Stopped ${NC}" [[ -f "$HOME/.xstartup" ]] && rm -rf "$HOME/.xstartup" elif [[ "\$1" == "-h" ]]; then echo -e "tx11stop to stop termux:x11" echo -e "tx11stop -f to kill termux:x11" fi exec 2>/dev/null EOF else cat <"$PREFIX/bin/tx11stop" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=\$(grep TracerPid "/proc/\$\$/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_PID" != 0 ]; then TRACER_NAME=\$(grep Name "/proc/\${TRACER_PID}/status" | cut -d \$'\t' -f 2) if [ "\$TRACER_NAME" = "proot" ]; then msg print_failed "tx11stop command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID termux-wake-unlock if [[ -f "$HOME/.xstartup" ]]; then de_startup=\$(cat "$HOME/.xstartup") else de_startup="$de_startup" fi termux_x11_pid=\$(pgrep -f "/system/bin/app_process / com.termux.x11.Loader :${display_number}") de_pid=\$(pgrep -f \$de_startup) if [[ -n "\$termux_x11_pid" ]] || [[ -n "\$de_pid" ]]; then kill -9 "\$termux_x11_pid" > /dev/null 2>&1 pkill -9 pulseaudio > /dev/null 2>&1 killall virgl_test_server > /dev/null 2>&1 pkill -9 $de_name-* > /dev/null 2>&1 pkill -9 dbus-* > /dev/null 2>&1 pkill -f com.termux.x11 > /dev/null 2>&1 if [[ ! -n "\$termux_x11_pid" ]] || [[ ! -n "\$de_pid" ]]; then echo -e "${G}Termux:X11 Stopped Successfully ${NC}" [[ -f "$HOME/.xstartup" ]] && rm -rf "$HOME/.xstartup" fi elif [[ "\$1" == "-f" ]] || [[ "\$1" == "--force" ]]; then pkill -f com.termux.x11 > /dev/null 2>&1 pkill -9 $de_name-* > /dev/null 2>&1 killall virgl_test_server > /dev/null 2>&1 pkill -9 pulseaudio > /dev/null 2>&1 pkill -9 dbus-* > /dev/null 2>&1 echo -e "${G}Termux:X11 Successfully Force Stopped ${NC}" [[ -f "$HOME/.xstartup" ]] && rm -rf "$HOME/.xstartup" elif [[ "\$1" == "-h" ]]; then echo -e "tx11stop to stop termux:x11" echo -e "tx11stop -f to kill termux:x11" fi exec 2>/dev/null EOF fi chmod +x "$PREFIX/bin/tx11stop" } function setup_termux_x11() { banner print_msg "${BOLD}Configuring Termux:X11" echo package_install_and_check "termux-x11-nightly" local repo_owner="termux" local repo_name="termux-x11" local latest_termux_x11_tag latest_termux_x11_tag=$(get_latest_release "termux" "termux-x11") local termux_x11_url="https://github.com/$repo_owner/$repo_name/releases/download/$latest_termux_x11_tag/" local assets assets=$(curl -s "https://api.github.com/repos/$repo_owner/$repo_name/releases/latest" | grep -oP '(?<="name": ")[^"]*') deb_assets=$(echo "$assets" | grep "termux-x11.*all.deb") download_file "$current_path/termux-x11.deb" "$termux_x11_url/$deb_assets" apt install "$current_path/termux-x11.deb" -y rm "$current_path/termux-x11.deb" # "sed -i '12s/^#//' "$HOME/.termux/termux.properties" setup_tx11start_cmd setup_tx11stop_cmd } function gui_termux_x11() { cat <<'EOF' >"$PREFIX/bin/gui" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=$(grep TracerPid "/proc/\$\$/status" | cut -d $'\t' -f 2) if [ "$TRACER_PID" != 0 ]; then TRACER_NAME=$(grep Name "/proc/${TRACER_PID}/status" | cut -d $'\t' -f 2) if [ "$TRACER_NAME" = "proot" ]; then msg print_failed "gui command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID forward_display() { echo "${R}[${C}-${R}]${G} Starting display on: ${given_ip}:${display_port} ${NC}" pkill -9 "$de_startup" >/dev/null 2>&1 pulseaudio --start --exit-idle-time=-1 pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1 rm -rf ~/.config/pulse/*-runtime/pid >/dev/null 2>&1 pactl load-module module-sles-source >/dev/null 2>&1 export XDG_RUNTIME_DIR=/data/data/com.termux/files/usr/tmp mkdir -p "$XDG_RUNTIME_DIR" env DISPLAY=${given_ip}:${display_port} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg dbus-launch --exit-with-session $de_startup } case $1 in --start | -l) tx11start ;; --display | -d) if [[ "$2" == *":"* ]]; then # Everything before the last colon given_ip="${2%:*}" # Everything after the last colon display_port="${2##*:}" else given_ip="$2" display_port="0" fi if [ -z "$given_ip" ]; then print_failed "No IP address provided" echo -e "Usage: gui --display [:]\nExamples:\n gui --display 192.168.1.100:0\n gui --display 192.168.1.100" exit 1 fi forward_display unset given_ip display_port ;; --stop | -s) tx11stop ;; --kill | -k | -kill) tx11stop -f print_success "gui services killed successfully" ;; --help | -h) echo -e "gui --start / gui -l to start termux:x11" echo -e "gui --display / gui -d to forward display to IP address" echo -e "gui --stop / gui -s to stop termux:x11" echo -e "gui --kill / gui -k to kill gui services" ;; *) echo "${R}Invalid choise${NC}" gui -h ;; esac EOF } function gui_both() { cat <<'EOF' >"$PREFIX/bin/gui" #!/data/data/com.termux/files/usr/bin/bash source /data/data/com.termux/files/usr/etc/termux-desktop/common_functions # This code block is taken from:- https://github.com/termux/proot-distro/blob/master/proot-distro.sh#L172C1-L184C1 TRACER_PID=$(grep TracerPid "/proc/\$\$/status" | cut -d $'\t' -f 2) if [ "$TRACER_PID" != 0 ]; then TRACER_NAME=$(grep Name "/proc/${TRACER_PID}/status" | cut -d $'\t' -f 2) if [ "$TRACER_NAME" = "proot" ]; then msg print_failed "gui command should not be executed under PRoot.\${W}" msg exit 1 fi unset TRACER_NAME fi unset TRACER_PID forward_display() { echo "${R}[${C}-${R}]${G} Starting display on: ${given_ip}:${display_port} ${NC}" pkill -9 "$de_startup" >/dev/null 2>&1 pulseaudio --start --exit-idle-time=-1 pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1 rm -rf ~/.config/pulse/*-runtime/pid >/dev/null 2>&1 pactl load-module module-sles-source >/dev/null 2>&1 export XDG_RUNTIME_DIR=/data/data/com.termux/files/usr/tmp mkdir -p "$XDG_RUNTIME_DIR" env DISPLAY=${given_ip}:${display_port} XDG_CONFIG_DIRS=/data/data/com.termux/files/usr/etc/xdg dbus-launch --exit-with-session $de_startup & } case $1 in --start | -l) case $2 in tx11) tx11start ;; vnc) vncstart ;; *) echo -e "${R}Invalid choise. Use ${C}tx11${R} or ${C}vnc ${G}with it${NC}" ;; esac ;; --display | -d) if [[ "$2" == *":"* ]]; then # Everything before the last colon given_ip="${2%:*}" # Everything after the last colon display_port="${2##*:}" else given_ip="$2" display_port="0" fi if [ -z "$given_ip" ]; then print_failed "No IP address provided" echo -e "Usage: gui --display [:]\nExamples:\n gui --display 192.168.1.100:0\n gui --display 192.168.1.100" exit 1 fi forward_display unset given_ip display_port ;; --kill | -k | -kill) vncstop -f >/dev/null 2>&1 tx11stop -f >/dev/null 2>&1 print_success "gui services killed successfully" ;; --stop | -s) case $2 in tx11) tx11stop ;; vnc) vncstop ;; *) echo -e "${R}Invalid choise. Use ${C}tx11${R} or ${C}vnc ${G}with it${NC}" ;; esac ;; --help | -h) echo -e "Usage: gui [OPTION] [ARGUMENT]\n" echo -e "Options:" echo -e " --start, -l [tx11/vnc] Start a GUI (termux:x11 or VNC)" echo -e " --display, -d Forward display to IP address" echo -e " --stop, -s [tx11/vnc] Stop a GUI (termux:x11 or VNC)" echo -e " --kill, -k Kill both GUI services at once" echo -e " --help, -h Show this help message" ;; *) echo -e "${R}Invalid choice${NC}" gui -h ;; esac EOF } function gui_launcher() { check_and_delete "$PREFIX/bin/gui" package_install_and_check "xorg-xhost" if [[ "$gui_mode" == "termux_x11" ]]; then setup_termux_x11 gui_termux_x11 elif [[ "$gui_mode" == "both" ]]; then setup_termux_x11 setup_vnc gui_both else setup_termux_x11 gui_termux_x11 fi print_to_config "gui_mode" print_to_config "display_number" chmod +x "$PREFIX/bin/gui" check_and_create_directory "$PREFIX/share/applications/" cat <"$PREFIX/share/applications/killgui.desktop" [Desktop Entry] Version=1.0 Type=Application Name=Stop Desktop Comment=Kill or stop termux desktop Exec=gui --kill Icon=system-shutdown Categories=System; Path= Terminal=false StartupNotify=false EOF chmod 644 "$PREFIX/share/applications/killgui.desktop" cp "$PREFIX/share/applications/killgui.desktop" "$HOME/Desktop/" } function check_desktop_process() { banner print_msg "Checking Termux:X11 and $de_name setup or not..." echo sleep 0.5 # check tx11start file and start termux x11 to check termux x11 process if [[ -f "${PREFIX}/bin/tx11start" ]]; then print_success "Found tx11start file." print_msg "Starting Termux:X11 for checkup..." termux-x11 :"${display_number}" -xstartup xfce4-session >/dev/null 2>&1 & sleep 10 log_debug "$(cat "$PREFIX/bin/tx11start")" termux-reload-settings local termux_x11_pid termux_x11_pid=$(pgrep -f "app_process -Xnoimage-dex2oat / com.termux.x11.Loader :${display_number}") if [[ -n "$termux_x11_pid" ]]; then print_success "Termux:X11 Working" else print_failed "No Termux:X11 process found" fi # check for the desktop environment related process local de_pid case "$de_name" in xfce) de_pid="$(pgrep xfce4)" ;; lxqt) de_pid="$(pgrep -f "lxqt-session|lxqt-panel")" ;; openbox) de_pid="$(pgrep -f "openbox|openbox-session")" ;; mate) de_pid="$(pgrep -f "mate-session|mate-panel")" ;; i3) de_pid="$(pgrep -f "i3|i3-with-shmlog")" ;; dwm) de_pid="$(pgrep dwm)" ;; bspwm) de_pid="$(pgrep bspwm)" ;; awesome) de_pid="$(pgrep -f awesome)" ;; fluxbox) de_pid="$(pgrep -f fluxbox)" ;; *) print_failed "Unknown desktop environment: $de_name" sleep 0.2 return 1 ;; esac if [[ -n "$de_pid" ]]; then print_success "$de_name is running fine" sleep 0.2 else print_failed "No $de_name process found, attempting to reinstall..." sleep 0.2 install_desktop # Check again after installation unset de_pid case "$de_name" in xfce) de_pid="$(pgrep xfce4)" ;; lxqt) de_pid="$(pgrep -f "lxqt-session|lxqt-panel|pcmanfm-qt")" ;; openbox) de_pid="$(pgrep -f "openbox|openbox-session")" ;; mate) de_pid="$(pgrep -f "mate-session|mate-panel|caja")" ;; i3) de_pid="$(pgrep -f "i3|i3-with-shmlog")" ;; dwm) de_pid="$(pgrep dwm)" ;; bspwm) de_pid="$(pgrep bspwm)" ;; awesome) de_pid="$(pgrep -f awesome)" ;; fluxbox) de_pid="$(pgrep -f fluxbox)" ;; *) print_failed "Unknown desktop environment: $de_name" sleep 0.2 return 1 ;; esac if [[ -n "$de_pid" ]]; then print_success "$de_name is now running after re-installation" sleep 0.2 else print_failed "$de_name failed to install or start, still after re-installation" sleep 0.2 return 1 fi fi # check tx11stop file and run it to check if there any termux x11 process exist or not if [[ -f "${PREFIX}/bin/tx11stop" ]]; then print_success "Found tx11stop file." log_debug "$(cat "$PREFIX/bin/tx11stop")" tx11stop -f # Wait a bit for the process to stop sleep 2 unset termux_x11_pid termux_x11_pid=$(pgrep -f "app_process -Xnoimage-dex2oat / com.termux.x11.Loader :${display_number}") if [[ -z "$termux_x11_pid" ]]; then print_success "Tx11stop command working" else print_failed "Tx11stop command not working" fi fi fi print_msg "Backing up current Termux:x11 preferences..." echo termux-x11 & termux-x11-preference list >"$HOME/old-termx-x11-preferences" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/termx-x11-preferences" print_msg "Adding custom Termux:x11 preferences..." echo termux-x11-preference /dev/null 2>&1 check_and_delete "termx-x11-preferences" } ######################################################################### # # Install Browser # ######################################################################### function browser_installer() { banner print_to_config "installed_browser" if [[ ${installed_browser} == "firefox" ]]; then package_install_and_check "firefox" elif [[ ${installed_browser} == "chromium" ]]; then package_install_and_check "chromium" elif [[ ${installed_browser} == "all" ]]; then package_install_and_check "firefox chromium" elif [[ ${installed_browser} == "skip" ]]; then print_msg "${C}Skipping Browser Installation..." echo sleep 2 else package_install_and_check "firefox" print_to_config "installed_browser" "firefox" fi } ######################################################################### # # Install Ide # ######################################################################### function ide_installer() { banner print_to_config "installed_ide" if [[ ${installed_ide} == "code" ]]; then package_install_and_check "code-oss code-is-code-oss" elif [[ ${installed_ide} == "geany" ]]; then package_install_and_check "geany" elif [[ ${installed_ide} == "neovim" ]]; then package_install_and_check "neovim lua51 lua-language-server stylua" package_install_and_check "tree-sitter-*" check_and_backup "$HOME/.config/nvim" if [[ "$installed_nvim_distro" == "nvchad" ]]; then git clone https://github.com/NvChad/starter ~/.config/nvim elif [[ "$installed_nvim_distro" == "lazyvim" ]]; then git clone https://github.com/LazyVim/starter ~/.config/nvim elif [[ "$installed_nvim_distro" == "mynvim" ]]; then git clone https://github.com/sabamdarif/mynvim.git ~/.config/nvim fi print_to_config "installed_nvim_distro" check_and_delete "$HOME/.config/nvim/.git" elif [[ ${installed_ide} == "all" ]]; then package_install_and_check "code-oss code-is-code-oss geany neovim lua51 lua-language-server stylua" package_install_and_check "tree-sitter-*" check_and_backup "$HOME/.config/nvim" if [[ "$installed_nvim_distro" == "nvchad" ]]; then git clone https://github.com/NvChad/starter ~/.config/nvim elif [[ "$installed_nvim_distro" == "lazyvim" ]]; then git clone https://github.com/LazyVim/starter ~/.config/nvim elif [[ "$installed_nvim_distro" == "mynvim" ]]; then git clone https://github.com/sabamdarif/mynvim.git ~/.config/nvim fi print_to_config "installed_nvim_distro" check_and_delete "$HOME/.config/nvim/.git" elif [[ ${installed_ide} == "skip" ]]; then print_msg "${C}Skipping Ide Installation..." echo sleep 2 else package_install_and_check "code-oss code-is-code-oss" fi } ######################################################################### # # Install Media Player # ######################################################################### function media_player_installer() { banner print_to_config "installed_media_player" if [[ ${installed_media_player} == "vlc" ]]; then package_install_and_check "vlc-qt-static" elif [[ ${installed_media_player} == "mpv" ]]; then package_install_and_check "mpv" elif [[ ${installed_media_player} == "all" ]]; then package_install_and_check "vlc-qt-static mpv" elif [[ ${installed_media_player} == "skip" ]]; then print_msg "${C}Skipping Media Player Installation..." echo sleep 2 else package_install_and_check "vlc-qt-static" fi } ######################################################################### # # Install Photo Editor # ######################################################################### function setup_gimp_plugins() { package_install_and_check "gimp-resynthesizer" ### un-comment this if you want the bleeding edge version of resynthesizer # download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/install-resynthesizer-termux" # if [[ -f "install-resynthesizer-termux" ]]; then # chmod +x install-resynthesizer-termux # source install-resynthesizer-termux # fi } function photo_editor_installer() { banner print_to_config "installed_photo_editor" if [[ ${installed_photo_editor} == "gimp" ]]; then package_install_and_check "gimp" setup_gimp_plugins elif [[ ${installed_photo_editor} == "inkscape" ]]; then package_install_and_check "inkscape" elif [[ ${installed_photo_editor} == "all" ]]; then package_install_and_check "gimp inkscape" setup_gimp_plugins elif [[ ${installed_photo_editor} == "skip" ]]; then print_msg "${C}Skipping Photo Editor Installation..." echo sleep 2 else package_install_and_check "gimp" fi } ######################################################################### # # Install Software Manager # ######################################################################### function install_termux_desktop_appstore() { banner print_msg "${C}Setting up AppStore..." echo download_file "https://raw.githubusercontent.com/sabamdarif/Termux-AppStore/refs/heads/src/appstore" chmod +x "appstore" ./appstore --install v0.5.4 cp "${PREFIX}/share/applications/org.sabamdarif.termux.appstore.desktop" "/data/data/com.termux/files/home/Desktop" chmod +x /data/data/com.termux/files/home/Desktop/org.sabamdarif.termux.appstore.desktop } ######################################################################### # # Setup shell bash / zsh # ######################################################################### function get_shellrc_path() { if [[ -z "$shell_name" ]]; then shell_name=$(basename "$SHELL") fi if [[ "$shell_name" == "bash" ]]; then shell_rc_file="$HOME/.bashrc" elif [[ "$shell_name" == "zsh" ]]; then shell_rc_file="$HOME/.zshrc" else print_failed "Unable to get shellrc path" exit 1 fi } function setup_zsh() { banner shell_name="zsh" print_msg "${BOLD}Configuring zsh.." package_install_and_check "zsh git" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/setup-zsh" chmod +x setup-zsh # shellcheck disable=SC1091 source setup-zsh check_and_delete "setup-zsh" if [[ -f "$HOME/.zshrc" ]]; then print_success "zsh setup successfully" fi clear print_to_config "selected_zsh_theme_name" } function setup_bash() { banner shell_name="bash" print_msg "${BOLD}Configuring bash.." package_install_and_check "git" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/setup-bash" chmod +x setup-bash # shellcheck disable=SC1091 source setup-bash check_and_delete "setup-bash" if [[ -f "$HOME/.bashrc" ]]; then print_success "bash setup successfully" fi clear } function setup_shell() { print_to_config "chosen_shell_name" if [[ "$chosen_shell_name" == "zsh" ]]; then setup_zsh elif [[ "$chosen_shell_name" == "bash" ]] || [[ "$chosen_shell_name" == "bash_with_ble" ]]; then setup_bash fi get_shellrc_path } function terminal_utility_setup() { if [[ "$terminal_utility_setup_answer" == "n" ]]; then banner print_msg "${C}Skipping Terminal Utility Setup..." echo else banner print_msg "${C}${BOLD}Configuring Terminal Utility For Termux..." echo package_install_and_check "bat eza zoxide fastfetch openssh fzf" if [[ "$PACKAGE_MANAGER" == "apt" ]]; then package_install_and_check "nala" fi check_and_backup "$PREFIX/etc/motd" check_and_backup "$PREFIX/etc/motd-playstore" check_and_backup "$PREFIX/etc/motd.sh" download_file "$PREFIX/etc/motd.sh" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/motd.sh" if grep -q "motd.sh$" "$PREFIX/etc/termux-login.sh"; then sed -i "s|.*motd\.sh$|bash $PREFIX/etc/motd.sh|" "$PREFIX/etc/termux-login.sh" else echo "bash $PREFIX/etc/motd.sh" >>"$PREFIX/etc/termux-login.sh" fi check_and_create_directory "$HOME/.termux" check_and_backup "$HOME/.termux/colors.properties $HOME/.termux/termux.properties $HOME/.aliases $HOME/.nanorc" check_and_create_directory "$HOME/.config/fastfetch" download_file "$HOME/.config/fastfetch/config.jsonc" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/config.jsonc" download_file "$HOME/.termux/termux.properties" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/termux.properties" download_file "$HOME/.aliases" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/.aliases" download_file "$HOME/.nanorc" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/.nanorc" download_file "$HOME/.termux/colors.properties" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/colors.properties" download_file "$PREFIX/bin/termux-ssh" "https://raw.githubusercontent.com/sabamdarif/simple-linux-scripts/main/termux-ssh" && chmod +x "$PREFIX/bin/termux-ssh" download_file "$PREFIX/bin/termux-fastest-repo" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/termux-fastest-repo" chmod +x "$PREFIX/bin/termux-fastest-repo" download_file "$PREFIX/bin/termux-color" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/termux-color" chmod +x "$PREFIX/bin/termux-color" download_file "$PREFIX/bin/termux-nf" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/termux-nf" chmod +x "$PREFIX/bin/termux-nf" cp "$shell_rc_file" "${shell_rc_file}-2" check_and_backup "$shell_rc_file" mv "${shell_rc_file}-2" "${shell_rc_file}" cat <>"$HOME/.shell_rc_content" # set zoxide as cd eval "\$(zoxide init --cmd cd ${shell_name})" # FZF color scheme export FZF_DEFAULT_OPTS=" \ --color=bg+:#363a4f,bg:#24273a,spinner:#f4dbd6,hl:#ed8796 \ --color=fg:#cad3f5,header:#ed8796,info:#c6a0f6,pointer:#f4dbd6 \ --color=marker:#b7bdf8,fg+:#cad3f5,prompt:#c6a0f6,hl+:#ed8796 \ --color=selected-bg:#494d64 \ --color=border:#363a4f,label:#cad3f5" EOF fi cat <>"$HOME/.shell_rc_content" # print your current termux-desktop configuration alias 'tdconfig'='cat "$CONFIG_FILE"' if [[ \$HOME != *termux* ]]; then export DISPLAY=:$display_number fi EOF if [[ "$distro_add_answer" == "y" ]]; then cat <>"$HOME/.shell_rc_content" # open the folder where all the apps added by proot-distro are located alias 'pdapps'='cd /data/data/com.termux/files/usr/share/applications/pd_added && ls' EOF fi if [[ "$PACKAGE_MANAGER" == "apt" ]]; then cat <<'EOF' >>"$HOME/.shell_rc_content" apt_wrapper() { # First check if nala is actually installed. If not fall back to the apt if ! command -v nala >/dev/null 2>&1; then echo "nala not found, falling back to apt." command apt "$@" return $? fi # If no argument given then run nala to print help menu if [ -z "$1" ]; then command nala return fi local cmd="$1" shift case "$cmd" in install | in | add) command nala install "$@" ;; se* | sr | find) command nala search "$@" ;; up | update) command nala update "$@" ;; upg*) command nala upgrade "$@" ;; show | info) command nala show "$@" ;; cl*) command nala clean "$@" ;; ap | autopurge) command nala autopurge "$@" ;; un* | rem* | rm | del* | r) command nala remove "$@" ;; list-up*) command nala list --upgradable ;; *) # pass the command ($cmd) along with the rest of the arguments # although i don't think we need to pass $@ # but i still did it just to be in the safe side command nala "$cmd" "$@" ;; esac } alias apt='apt_wrapper' EOF fi echo "[[ -f ${HOME}/.shell_rc_content ]] && source ${HOME}/.shell_rc_content" >>"${shell_rc_file}" if [[ "$terminal_utility_setup_answer" == "y" ]]; then echo "[[ -f ${HOME}/.aliases ]] && source ${HOME}/.aliases" >>"${shell_rc_file}" fi print_to_config "terminal_utility_setup_answer" } ######################################################################### # # Setup File Manager Utility # ######################################################################### function install_fm_tools() { if [[ "$fm_tools" == "y" ]]; then banner print_msg "${BOLD}Installing File Manager Tools..." check_and_backup "$HOME/.local/share/nautilus/scripts" check_and_create_directory "$HOME/.local/share/nautilus/scripts" cd "$HOME" || exit 1 git clone -b termux https://github.com/sabamdarif/nautilus-scripts cd nautilus-scripts || exit 1 bash setup-termux.sh cd "$HOME" || exit 1 check_and_delete "nautilus-scripts" fi print_to_config "fm_tools" } ######################################################################### # # Install Fonts # ######################################################################### function setup_fonts() { banner print_msg "${BOLD}Installing ${sel_base_name} Nerd Font..." package_install_and_check "nerdfix fontconfig-utils" check_and_create_directory "$HOME/.termux" check_and_create_directory "$HOME/.fonts" check_and_backup "$HOME/.termux/font.ttf" if [[ -z "$latest_nf_version" ]]; then latest_nf_version=$(get_latest_release "ryanoasis" "nerd-fonts") fi if [[ -z "$sel_asset_name" ]]; then sel_base_name="0xProto" fi print_to_config "sel_base_name" download_and_extract "https://github.com/ryanoasis/nerd-fonts/releases/download/${latest_nf_version}/${sel_base_name}.tar.xz" "$HOME/.fonts" nerd_font_file=$(find "$HOME/.fonts" -type f \( -iname "${sel_base_name}*NerdFont-Regular.ttf" -o -iname "${sel_base_name}*NerdFont-Regular.otf" \) | head -n1) if [[ -z "$nerd_font_file" ]]; then nerd_font_file=$(find "$HOME/.fonts" -type f -iname "*NerdFont*" | head -n1) fi check_and_delete "$HOME/.fonts/README.md $HOME/.fonts/LICENSE" if [[ -n "$nerd_font_file" ]]; then cp "$nerd_font_file" "$HOME/.termux/font.ttf" fc-cache -f else print_failed "Could not locate a NerdFont-Regular file for ${sel_base_name}." exit 1 fi } ######################################################################### # # Install Wine # ######################################################################### function run_wine_shortcut_script() { print_success "Adding wine desktop shortcuts..." download_file "add-wine-shortcut" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/other/add-wine-shortcut" chmod +x "add-wine-shortcut" source add-wine-shortcut check_and_delete "add-wine-shortcut" } function setup_wine() { banner print_to_config "installed_wine" if [[ "$installed_wine" == "stock" ]]; then print_msg "${BOLD}Installing Wine Natively In Termux" echo package_install_and_check "wine-stable" run_wine_shortcut_script elif [[ "$installed_wine" == "mobox" ]]; then print_msg "${BOLD}Addind Mobox Launch Option To Termux" echo print_msg "${C}${BOLD}After the installation finishes, make sure to install Mobox using their official instructions" echo print_msg "${BOLD}Mobox:- ${C}https://github.com/olegos2/mobox" echo sleep 4 download_file "$PREFIX/bin/wine" "https://raw.githubusercontent.com/LinuxDroidMaster/Termux-Desktops/main/scripts/termux_native/mobox_run.sh" chmod +x "$PREFIX/bin/wine" cp "$PREFIX/share/applications/wine-explorer.desktop" "$HOME/Desktop/MoboxExplorer.desktop" run_wine_shortcut_script elif [[ "$installed_wine" == "wine_hangover" ]]; then package_install_and_check "hangover-wine" run_wine_shortcut_script if [[ ! -f "$PREFIX/bin/wine" ]]; then ln -s "$PREFIX/bin/hangover-wine" "$PREFIX/bin/wine" fi elif [[ "$installed_wine" == "skip" ]]; then print_msg "${C}Skipping wine Installation..." else print_msg "Installing Wine Natively In Termux" echo package_install_and_check "wine-stable" run_wine_shortcut_script fi } ######################################################################### # # Add Autostart # ######################################################################### function add_vnc_autostart() { print_msg "${BOLD}Adding vnc to autostart" if grep -q "^vncstart" "$shell_rc_file"; then print_msg "Termux:X11 start already exist" else cat <>"$shell_rc_file" # Start Vnc if ! pgrep Xvnc > /dev/null; then echo "${G}Starting Vnc...${NC}" vncstart fi EOF fi } function add_tx11_autostart() { print_msg "${BOLD}Adding Termux:x11 to autostart" if grep -q "^tx11start" "$shell_rc_file"; then print_msg "Termux:X11 start already exist" else cat <>"$shell_rc_file" # Start Termux:X11 termux_x11_pid=\$(pgrep -f "app_process -Xnoimage-dex2oat / com.termux.x11.Loader :${display_number}") if [ -z "\$termux_x11_pid" ]; then echo "${G}Starting Termux:x11...${NC}" tx11start fi EOF fi } function add_to_autostart() { print_to_config "de_on_startup" if [[ "$de_on_startup" == "y" ]]; then if [[ "$default_gui_mode" == "vnc" ]]; then add_vnc_autostart elif [[ "$default_gui_mode" == "termux_x11" ]] || [[ "$gui_mode" == "termux_x11" ]]; then add_tx11_autostart fi if [[ "$gui_mode" == "both" ]]; then print_to_config "default_gui_mode" fi fi } ######################################################################### # # Finish | Notes # ######################################################################### function cleanup_cache() { banner print_msg "Cleaning up the cache..." if [[ "$PACKAGE_MANAGER" == "pacman" ]]; then pacman -Scc --noconfirm else apt clean all fi } function add_common_function() { check_and_delete "$PREFIX/etc/termux-desktop/common_functions" cat <<'EOF' >"$PREFIX/etc/termux-desktop/common_functions" #!/data/data/com.termux/files/usr/bin/bash R="$(printf '\033[1;31m')" G="$(printf '\033[1;32m')" Y="$(printf '\033[1;33m')" B="$(printf '\033[1;34m')" C="$(printf '\033[1;36m')" NC="$(printf '\033[0m')" BOLD="$(printf '\033[1m')" TERMUX_DESKTOP_PATH="/data/data/com.termux/files/usr/etc/termux-desktop" CONFIG_FILE="$TERMUX_DESKTOP_PATH/configuration.conf" LOG_FILE="/data/data/com.termux/files/home/termux-desktop.log" EOF typeset -f check_termux log_debug print_success print_failed print_warn print_msg wait_for_keypress check_and_create_directory check_and_delete check_and_backup download_file check_and_restore detact_package_manager package_install_and_check package_check_and_remove get_file_name_number extract_zip_with_progress extract_archive download_and_extract count_subfolders confirmation_y_or_n get_latest_release install_font_for_style select_an_option read_conf print_to_config >>"$PREFIX/etc/termux-desktop/common_functions" chmod +x "$PREFIX/etc/termux-desktop/common_functions" } function delete_installer_file() { current_script_path="$(realpath "$0")" if [[ "$current_script_path" != */bin* ]]; then if [[ -f "${current_path}/setup-termux-desktop" ]]; then (exec rm -- "${current_path}/setup-termux-desktop") & else print_failed "Installer file not found" fi fi } function notes() { banner print_msg "Installation Successfull..." echo sleep 2 print_msg "${C}${BOLD}Now Restart Termux ${G}(Must)" echo print_msg "${C}${BOLD}Some basic commands:-${G}(Must know)" echo print_msg "tx11start to start the gui with termux:x11" echo print_msg "tx11stop to stop the gui with termux:x11" echo print_msg "tx11stop -f to force stop the gui with termux:x11" echo if [[ "$gui_mode" == "both" ]]; then print_msg "vncstart to start the gui with vnc" echo print_msg "vncstop to stop the gui with vnc" echo fi if [[ "$distro_add_answer" == "y" ]]; then print_msg "${C}run:- $selected_distro, to login into $selected_distro" fi echo print_msg "${C}${BOLD}See Uses Section in github to know how to use it" echo print_msg "${C}URL:- ${B}https://github.com/sabamdarif/termux-desktop/blob/main/README.md#5-usage-instructions" echo if [[ "$distro_add_answer" == "y" ]]; then print_msg "${C}${BOLD}See how to use Linux distro container" echo print_msg "${C}URL:- ${B}https://github.com/sabamdarif/termux-desktop/blob/main/docs/proot-container.md" fi } ######################################################################### # # Remove # ######################################################################### function remove_desktop_environments() { if [[ "$de_name" == "xfce" ]]; then package_check_and_remove "xfce4 xfce4-goodies xfce4-pulseaudio-plugin xfce4-battery-plugin xfce4-docklike-plugin xfce4-notifyd-static kvantum gtk2-engines-murrine" elif [[ "$de_name" == "lxqt" ]]; then package_check_and_remove "lxqt xorg-xsetroot papirus-icon-theme xwayland kvantum" elif [[ "$de_name" == "openbox" ]]; then package_check_and_remove "openbox polybar xorg-xsetroot lxappearance wmctrl feh xwayland kvantum thunar firefox mpd rofi bmon xcompmgr xfce4-settings gedit" elif [[ "$de_name" == "mate" ]]; then package_check_and_remove "mate*" package_check_and_remove "marco mousepad xfce4-taskmanager lximage-qt" elif [[ "$de_name" == "i3wm" ]]; then package_check_and_remove "i3" elif [[ "$de_name" == "dwm" ]]; then package_check_and_remove "dwm" elif [[ "$de_name" == "bspwm" ]]; then package_check_and_remove "bspwm" elif [[ "$de_name" == "awesome" ]]; then package_check_and_remove "awesome" elif [[ "$de_name" == "fluxbox" ]]; then package_check_and_remove "fluxbox xorg-xsetroot xorg-xprop lxappearance wmctrl feh firefox rofi bmon xcompmgr gtk3 gedit xmllint" elif [[ "$de_name" == "gnome" ]]; then package_check_and_remove "gnome*" package_check_and_remove "thunar xfce4-terminal" elif [[ "$de_name" == "cinnamon" ]]; then package_check_and_remove "cinnamon nemo gnome-terminal gnome-screenshot eog" fi } function remove_termux_desktop() { if [[ ! -e "$CONFIG_FILE" ]]; then print_msg "${C}${BOLD}Please Install Termux Desktop First" exit 1 else banner print_msg "${R}${BOLD} Remove Termux Desktop" echo "" confirmation_y_or_n "Are You Sure You Want To Remove Termux Desktop Completely" ask_remove if [[ "$ask_remove" == "n" ]]; then print_msg "${BOLD}Canceling..." exit 0 else print_msg "${R}${BOLD}Removeing Termux Desktop" sleep 3 read_conf #remove basic packages package_check_and_remove "pulseaudio x11-repo tur-repo" #remove desktop related packages remove_desktop_environments package_check_and_remove "kvantum xwayland pulseaudio file-roller pavucontrol gnome-font-viewer evince galculator libwayland-protocols xorg-xrdb" #remove zsh if [[ "$chosen_shell_name" == "zsh" ]]; then package_check_and_remove "zsh" check_and_delete "$HOME/.zsh_history $HOME/.zshrc" fi #remove terminal utility if [[ "$terminal_utility_setup_answer" == "y" ]]; then check_and_delete "$PREFIX/etc/motd.sh $HOME/.termux $HOME/.fonts/font.ttf $HOME/.termux/colors.properties" check_and_restore "$PREFIX/etc/motd" check_and_restore "$PREFIX/etc/motd-playstore" check_and_restore "$PREFIX/etc/motd.sh" check_and_restore "$HOME/.termux/colors.properties" if grep -q "motd.sh$" "$PREFIX/etc/termux-login.sh"; then sed -i "s|.*motd\.sh$|# |" "$PREFIX/etc/termux-login.sh" fi package_check_and_remove "nerdfix fontconfig-utils bat eza" fi #remove browser if [[ "$installed_browser" == "firefox" ]]; then package_check_and_remove "firefox" elif [[ "$installed_browser" == "chromium" ]]; then package_check_and_remove "chromium" elif [[ "$installed_browser" == "all" ]]; then package_check_and_remove "firefox chromium" fi #remove ide if [[ "$installed_ide" == "code" ]]; then package_check_and_remove "code-oss code-is-code-oss" elif [[ "$installed_ide" == "neovim" ]]; then package_check_and_remove "neovim lua51 lua-language-server stylua tree-sitter-lua" elif [[ "$installed_ide" == "geany" ]]; then package_check_and_remove "geany" elif [[ "$installed_ide" == "all" ]]; then package_check_and_remove "code-oss code-is-code-oss geany neovim lua51 lua-language-server stylua tree-sitter-lua" fi #remove media player if [[ "$installed_media_player" == "vlc" ]]; then package_check_and_remove "vlc-qt-static" elif [[ "$installed_media_player" == "audacious" ]]; then package_check_and_remove "audacious" elif [[ "$installed_media_player" == "both" ]]; then package_check_and_remove "vlc-qt-static audacious" fi #remove photo editor if [[ "$installed_photo_editor" == "gimp" ]]; then package_check_and_remove "gimp" elif [[ "$installed_photo_editor" == "audacious" ]]; then package_check_and_remove "audacious" elif [[ "$installed_photo_editor" == "both" ]]; then package_check_and_remove "gimp audacious" fi #remove wine if [[ "$installed_wine" == "stock" ]]; then package_check_and_remove "wine" elif [[ "$installed_wine" == "mobox" ]]; then print_msg "${C}${BOLD}Make Sure To Uninstall Mobox Using Their Instruction" check_and_delete "$HOME/Desktop/MoboxExplorer.desktop" sleep 4 elif [[ "$installed_wine" == "wine_hangover" ]]; then package_check_and_remove "hangover-wine" fi check_and_delete "$PREFIX/bin/wine $PREFIX/share/applications/wine-*" #remove styles if [[ "$style_answer" == "5" ]]; then package_check_and_remove "eww" fi #Remove folders and other files check_and_delete "$PREFIX/share/backgrounds $themes_folder $icons_folder $PREFIX/etc/termux-desktop" check_and_delete "$HOME/.config/$the_config_dir" check_and_delete "$HOME/Desktop $HOME/Downloads $HOME/Videos $HOME/Pictures $HOME/Music" #remove hw packages package_check_and_remove "mesa-zink virglrenderer-mesa-zink vulkan-loader-android angle-android virglrenderer-android mesa-vulkan-icd-freedreno mesa-vulkan-icd-wrapper mesa-zink" #remove distro container if [[ "$distro_add_answer" == "y" ]]; then proot-distro remove "$selected_distro" proot-distro clear-cache package_check_and_remove "proot-distro" check_and_delete "$PREFIX/bin/$selected_distro $PREFIX/bin/pdrun" fi #remove vnc and termux x11 check_and_delete "$PREFIX/bin/gui" if [[ "$gui_mode" == "termux_x11" ]]; then package_check_and_remove "termux-x11-nightly xorg-xhost" check_and_delete "$PREFIX/bin/tx11start $PREFIX/bin/tx11stop" elif [[ "$gui_mode" == "both" ]]; then package_check_and_remove "termux-x11-nightly tigervnc xorg-xhost" check_and_delete "$PREFIX/bin/tx11start $PREFIX/bin/tx11stop $HOME/.vnc/xstartup $PREFIX/bin/vncstart $PREFIX/bin/vncstop $PREFIX/bin/gui $PREFIX/bin/tx11start $PREFIX/bin/tx11stop" # shellcheck disable=SC2164 cd "$PREFIX/share/zsh/site-functions" check_and_delete "_add2menu _distro _setup-termux-desktop _tx11start _tx11stop _vncstart _vncstop" # shellcheck disable=SC2164 cd "$PREFIX/share/bash-completion/completions" check_and_delete "add2menu distro setup-termux-desktop tx11start tx11stop vncstart vncstop" # shellcheck disable=SC2164 cd "$HOME" # remove appstore package_check_and_remove "aria2 python python3 cloneit" check_and_delete "${PREFIX}/opt/appstore" check_and_delete "${PREFIX}/share/applications/org.sabamdarif.termux.appstore.desktop" fi check_and_delete "$PREFIX/etc/termux-desktop $PREFIX/bin/setup-termux-desktop" clear print_msg "${BOLD}Everything remove successfully" fi fi } ######################################################################### # # Change Style # ######################################################################### function gui_check_up() { termux_x11_pid=$(pgrep -f "app_process -Xnoimage-dex2oat / com.termux.x11.Loader :${display_number}") vnc_server_pid=$(pgrep -f "vncserver") de_pid=$(pgrep -f "$de_startup") if [[ -n "$termux_x11_pid" ]] || [[ -n "$de_pid" ]] || [[ -n "$vnc_server_pid" ]] >/dev/null 2>&1; then echo "${G}Please Stop The Gui Desktop Server First${NC}" exit 0 fi } function change_style() { if [[ ! -e "$CONFIG_FILE" ]]; then echo -e "${C} It look like you haven't install the desktop yet\n Please install the desktop first${NC}" exit 1 else read_conf gui_check_up banner download_file "${current_path}/styles.md" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/docs/${de_name}_styles.md" style_name=$(grep -oP "^## $style_answer\..+?(?=(\n## \d+\.|\Z))" "${current_path}/styles.md" | sed -e "s/^## $style_answer\. //" -e "s/:$//" -e 's/^[[:space:]]*//;s/[[:space:]]*$//') check_and_delete "${current_path}/styles.md" print_msg "Your currently installed style is ${C}${BOLD}$style_name" echo sleep 2 unset style_name questions_theme_select rm -rf ~/.cache/sessions/* setup_config banner print_msg "Style changed successfully" echo print_msg "Your currently installed style is ${C}${BOLD}$style_name" fi } ######################################################################### # # Change Hardware Acceleration # ######################################################################### function do_hw_changes() { try_to_autodetect_gpu setup_device_gpu_model hw_questions update_sys hw_config if [[ "$gui_mode" == "termux_x11" ]]; then setup_tx11start_cmd some_fixes elif [[ "$gui_mode" == "both" ]]; then setup_tx11start_cmd setup_vncstart_cmd some_fixes fi if [[ "$distro_add_answer" == "y" ]]; then get_distro_container_source # shellcheck disable=SC1091 source "${current_path}/distro-container-setup" # set the required variables for pdrun if [[ "$selected_distro_type" == "chroot" ]]; then termux_home_link=" " else termux_home_link="--termux-home" fi final_user_name="$user_name" distro_app_launch_setup check_and_delete "${current_path}/distro-container-setup" fi } function change_hw() { # Check if the configuration file exists if [[ ! -e "$CONFIG_FILE" ]]; then print_warn "${C}It looks like you haven't installed the desktop yee. Please install the desktop first" exit 1 else read_conf local old_hw_option old_hw_option="${termux_hw_answer}" if [[ "$enable_hw_acc" == "y" ]]; then banner print_msg "Your current hardware acceleration api for Termux is: ${C}${BOLD}${termux_hw_answer}" if [[ "$distro_add_answer" == "y" ]]; then print_msg "Your current hardware acceleration api for $selected_distro is: ${C}${BOLD}${pd_hw_answer}" fi confirmation_y_or_n "Do you want to change hardware acceleration api" confirmation_change_hardware_acceleration if [[ "$confirmation_change_hardware_acceleration" == "y" ]]; then do_hw_changes read_conf if [[ "$old_hw_option" != "$termux_hw_answer" ]]; then print_success "${BOLD}Hardware acceleration method successfully changed to ${termux_hw_answer}" exit 0 elif [[ "$old_hw_option" == "$termux_hw_answer" ]]; then print_success "${BOLD}Hardware acceleration method is still on ${termux_hw_answer}" exit 0 else print_failed "Something went wrong during the hardware acceleration process..." exit 1 fi fi elif [[ "$enable_hw_acc" == "n" ]]; then print_msg "This option can only be used if have Hardware Acceleration enabled" confirmation_y_or_n "Do you want to enable Hardware Acceleration" confirmation_want_to_enable_hw if [[ "$confirmation_want_to_enable_hw" == "y" ]]; then enable_hw_acc="y" do_hw_changes read_conf if [[ "$enable_hw_acc" == "y" ]]; then print_success "${BOLD}Successfully enable hardware acceleration" else print_failed "Some issue occurred during the hardware acceleration change process..." fi elif [[ "$confirmation_want_to_enable_hw" == "n" ]]; then print_msg "Keeping Hardware Acceleration disabled" exit 0 fi fi fi } ######################################################################### # # Change Distro # ######################################################################### function add_distro_again() { print_msg "${BOLD}Do you want to add a Linux distro container" echo print_msg "It will help you to install those app which are not avilable in termux" echo print_msg "You can launch those installed apps from termux like other apps" echo confirmation_y_or_n "Do you want to continue" distro_add_answer if [[ "$distro_add_answer" == "y" ]]; then print_to_config "distro_add_answer" distro_questions if [[ "$enable_hw_acc" == "y" ]]; then distro_hw_questions # call setup_hw_environment_variables from hw-acceleration setup script # this is needed for pdrun command get_hw_acceleration_source # shellcheck disable=SC1091 source "${current_path}/enable-hw-acceleration" setup_hw_environment_variables check_and_delete "${current_path}/enable-hw-acceleration" fi distro_container_setup fi } function change_distro() { if [[ ! -e "$CONFIG_FILE" ]]; then echo -e "${C} It look like you haven't install the desktop yet\n Please install the desktop first${NC}" exit 1 else read_conf banner if [[ "$distro_add_answer" == "y" ]]; then local old_distro old_distro="${selected_distro}" if [[ -z "$selected_distro_type" ]]; then if command -v chroot-distro >/dev/null 2>&1; then selected_distro_type=chroot else selected_distro_type=proot fi fi if [[ "$selected_distro_type" == "chroot" ]]; then if ! timeout 3s su -c "ls /data/local/chroot-distro/installed-rootfs/$selected_distro" >/dev/null 2>&1; then print_failed "${selected_distro} isn't installed" add_distro_again exit 0 fi else if [[ ! -d "$PREFIX/var/lib/proot-distro/installed-rootfs/$selected_distro" ]]; then print_failed "${selected_distro} isn't installed" add_distro_again exit 0 fi fi print_msg "Your currently installed distro is: ${C}${BOLD}${selected_distro}" echo print_msg "${R}Changing distro will delete all the data from your previous distro" echo confirmation_y_or_n "Do you want to continue" distro_change_confirmation if [[ "$distro_change_confirmation" == "y" ]]; then choose_distro print_msg "Removing $selected_distro and it's data" "${selected_distro_type}"-distro remove "${old_distro}" check_and_delete "$PREFIX/share/applications/pd_added" check_and_delete "/data/data/com.termux/files/usr/share/bash-completion/completions/${old_distro}" check_and_delete "/data/data/com.termux/files/usr/share/zsh/site-functions/_${old_distro}" check_and_delete "$PREFIX/bin/$selected_distro" get_hw_acceleration_source # shellcheck disable=SC1091 source "${current_path}/enable-hw-acceleration" setup_hw_environment_variables check_and_delete "${current_path}/enable-hw-acceleration" if [[ "$pd_audio_config_answer" == "y" ]]; then rm "$HOME/.${selected_distro}-sound-access" fi echo distro_container_setup else print_msg "Canceling distro change process..." sleep 2 exit 0 fi else print_msg "It look like you haven't install any distro yet" echo add_distro_again fi fi } ######################################################################### # # Change Autostart # ######################################################################### function change_autostart() { read_conf get_shellrc_path if [[ "$de_on_startup" == "y" ]]; then confirmation_y_or_n "You are sure you want to change auto" confirmation_change_auto_start if [[ "$confirmation_change_auto_start" == "y" ]]; then if grep -q "^vncstart" "$shell_rc_file"; then sed -i '/# Start Vnc/,/fi/d' "$shell_rc_file" print_to_config "de_on_startup" "n" fi if grep -q "^tx11start" "$shell_rc_file"; then sed -i '/# Start Termux:X11/,/fi/d' "$shell_rc_file" print_to_config "de_on_startup" "n" fi print_msg "Auto start disabled" else print_msg "Keeping auto start enabled" fi elif [[ "$de_on_startup" == "n" ]]; then confirmation_y_or_n "You haven't have auto start enable, do you want to enable it" confirmation_enable_auto_start if [[ "$confirmation_enable_auto_start" == "y" ]]; then if [[ "$gui_mode" == "both" ]]; then print_msg "You chose both vnc and termux:x11 to access gui mode" echo print_msg "Which will be your default" echo echo "${Y}1. Termux:x11${NC}" echo echo "${Y}2. Vnc${NC}" echo select_an_option 2 1 autostart_gui_mode_num if [[ "$autostart_gui_mode_num" == "1" ]]; then default_gui_mode="termux_x11" elif [[ "$autostart_gui_mode_num" == "2" ]]; then default_gui_mode="vnc" fi fi de_on_startup=y print_to_config "de_on_startup" add_to_autostart else print_msg "Keeping auto start disabled" fi fi } ######################################################################### # # Change Display Port # ######################################################################### # change the Display Port/Display Number where it will show the output function change_display() { read_conf gui_check_up if [[ "$gui_mode" == "termux_x11" ]] || [[ "$gui_mode" == "both" ]]; then print_msg "${BOLD}Your Current Display Port: ${display_number}" echo confirmation_y_or_n "Do you want to change the display port" change_display_port if [[ "$change_display_port" == "y" ]]; then while true; do read -r -p "${R}[${C}-${R}]${Y}${BOLD} Type the Display Port number: ${NC}" display_number if [[ "$display_number" =~ ^[0-9]+$ ]]; then break else print_warn "${R}Please enter a valid number between 0-9" fi done # shellcheck disable=SC2034 call_from_change_display=true hw_config setup_tx11start_cmd print_to_config "display_number" sed -i "s|DISPLAY=:[0-9]*|DISPLAY=:$display_number|" "${PREFIX}/bin/$selected_distro" log_debug "Type the Display Port number: $display_number" fi else print_msg "Changing display port only supported in Termux:x11" fi } ######################################################################### # # Change Desktop Environment / window manager # ######################################################################### function change_de() { read_conf gui_check_up print_msg "Your currently installed environments is: ${C}${BOLD}${de_name}" echo print_warn "${R}Changing environment will delete all you previous configuration for that environment" echo confirmation_y_or_n "Do you want to continue" de_change_confirmation if [[ "$de_change_confirmation" == "y" ]]; then old_de_name="$de_name" ask_to_chose_de update_sys install_required_packages install_desktop if [[ "$style_answer" == "0" ]]; then banner print_msg "${BOLD}Configuring Stock $de_name Style..." echo print_to_config "style_answer" ext_setup_for_stock else setup_config fi if [[ "$enable_hw_acc" == "y" ]]; then hw_config fi gui_launcher print_msg "Removeing old $old_de_name environment" de_name="$old_de_name" remove_desktop_environments unset de_name read_conf check_desktop_process add_to_autostart echo " " print_msg "Your current environment is $de_name" fi } ######################################################################### # # Reinstall themes # ######################################################################### function reinstall_themes() { read_conf gui_check_up tmp_themes_folder="$PREFIX/tmp/themes" check_and_create_directory "$tmp_themes_folder" print_msg "Reinstalling Themes..." download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/theme.tar.gz" "$tmp_themes_folder" local theme_names theme_names=$(ls "$tmp_themes_folder") local theme_name for theme_name in $theme_names; do check_and_delete "$themes_folder/$theme_name" mv "$tmp_themes_folder/$theme_name" "$themes_folder/" done print_msg "${BOLD}Themes reinstall successfully" } ######################################################################### # # Reinstall icons # ######################################################################### function reinstall_icons() { read_conf gui_check_up tmp_icons_folder="$PREFIX/tmp/icons" check_and_create_directory "$tmp_icons_folder" package_install_and_check "gdk-pixbuf" print_msg "Reinstalling Icons..." download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/icon.tar.gz" "$tmp_icons_folder" local icon_themes_names icon_themes_names=$(ls "$tmp_icons_folder") local icon_theme for icon_theme in $icon_themes_names; do check_and_delete "$icons_folder/$icon_theme" mv "$tmp_icons_folder/$icon_theme" "$icons_folder/" print_msg "Creating icon cache..." gtk-update-icon-cache -f -t "$icons_folder/$icons_theme" gtk-update-icon-cache -f -t "$PREFIX/share/icons/$icons_theme" done print_msg "${BOLD}Icons reinstall successfully" } ######################################################################### # # Reinstall config # ######################################################################### function reinstall_config() { read_conf gui_check_up tmp_config_folder="$PREFIX/tmp/config" check_and_create_directory "$tmp_config_folder" print_msg "Reinstalling Config..." download_and_extract "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/setup-files/setup-files/${de_name}/look_${style_answer}/config.tar.gz" "$tmp_config_folder" local dot_config_file_names dot_config_file_names=$(ls "$tmp_config_folder") local dot_config_file for dot_config_file in $dot_config_file_names; do check_and_delete "$HOME/.config/$dot_config_file" mv "$tmp_config_folder/$dot_config_file" "$HOME/.config/" done print_msg "${BOLD}Config reinstall successfully" } ######################################################################### # # Some Fixes | Finishing Tasks # ######################################################################### function add_auto_completion() { banner print_msg "Adding auto completions..." check_and_create_directory "/data/data/com.termux/files/usr/share/zsh/site-functions" # shellcheck disable=SC2164 cd /data/data/com.termux/files/usr/share/zsh/site-functions download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_setup-termux-desktop" if [[ "$gui_mode" == "both" ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_vncstart" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_vncstop" fi download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_tx11start" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_tx11stop" if [[ "$distro_add_answer" == "y" ]]; then download_file "_${selected_distro}" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_distro" sed -i "s/distro/${selected_distro}/g" "_${selected_distro}" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/zsh/_add2menu" fi check_and_create_directory "/data/data/com.termux/files/usr/share/bash-completion/completions" # shellcheck disable=SC2164 cd /data/data/com.termux/files/usr/share/bash-completion/completions download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/setup-termux-desktop" if [[ "$gui_mode" == "both" ]]; then download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/vncstart" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/vncstop" fi download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/tx11start" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/tx11stop" if [[ "$distro_add_answer" == "y" ]]; then download_file "${selected_distro}" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/distro" sed -i "s/distro/${selected_distro}/g" "${selected_distro}" download_file "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/completion/bash/add2menu" fi cd "$HOME" || return 1 } function disable_vblank_mode() { if [[ "$de_name" == "xfce" ]]; then sed -i 's|||' "$HOME/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml" fi } function some_fixes() { # samsung oneui-6 audio fixes local device_brand_name device_brand_name=$(getprop ro.product.brand | cut -d ' ' -f 1) if [[ $device_brand_name == samsung* && $ANDROID_VERSION -ge 14 ]]; then package_install_and_check "libandroid-stub" # if [[ -e "/system/lib64/libskcodec.so" ]]; then # grep -q 'export LD_PRELOAD=/system/lib64/libskcodec.so' "$shell_rc_file" || echo 'export LD_PRELOAD=/system/lib64/libskcodec.so' >>"$shell_rc_file" # fi fi # fix blank export in tx11start sed -i '/^export\s*$/d' "$PREFIX/bin/tx11start" # tx11start and vncstart if [[ "$termux_hw_answer" == "mesa_freedreno" ]] || [[ "$termux_hw_answer" == "mesa_zink_freedreno" ]] || [[ "$termux_hw_answer" == "freedreno_kgsl" ]] || [[ $termux_hw_answer == "zink_with_mesa" ]] || [[ $termux_hw_answer == "zink_with_mesa_zink" ]]; then sed -i "/if ! \$use_nogpu; then/,/fi/ {/if \$use_debug; then/,/fi/d}" "$PREFIX/bin/tx11start" sed -i "s/^[[:space:]]*&[[:space:]]*$/ /" "$PREFIX/bin/vncstart" fi if [[ "$exp_termux_vulkan_hw_answer" != "skip" ]]; then disable_vblank_mode if [[ "$installed_browser" == "chromium" ]] || [[ "$installed_browser" == "all" ]]; then sed -i 's|Exec=/data/data/com.termux/files/usr/bin/chromium-browser %U|Exec=/data/data/com.termux/files/usr/bin/chromium-browser --enable-features=Vulkan %U|' /data/data/com.termux/files/usr/share/applications/chromium.desktop fi if [[ "$installed_ide" == "code" ]] || [[ "$installed_ide" == "all" ]]; then sed -i 's|/data/data/com.termux/files/usr/bin/code-oss|/data/data/com.termux/files/usr/bin/code-oss --enable-features=Vulkan|g' /data/data/com.termux/files/usr/share/applications/code-oss* fi fi # some fixes for gnome and cinnamon desktop if [[ "$de_name" == "gnome" ]] || [[ "$de_name" == "cinnamon" ]]; then sed -i "s|||" "$PREFIX/share/dbus-1/system.d/org.freedesktop.UPower.conf" if [[ "$de_name" == "gnome" ]]; then cat <"$PREFIX/share/gnome-session/sessions/minimal.session" [GNOME Session] Name=Minimal GNOME RequiredComponents=org.gnome.Shell;org.gnome.SettingsDaemon.A11ySettings;org.gnome.SettingsDaemon.Color;org.gnome.SettingsDaemon.Datetime;org.gnome.SettingsDaemon.Housekeeping;org.gnome.SettingsDaemon.Keyboard;org.gnome.SettingsDaemon.Sound; DefaultProvider-wm=gnome-shell DesktopName=GNOME EOF cat <"$PREFIX/bin/gnome-session-minimal" rm -rf /data/data/com.termux/files/usr/var/run/dbus/pid dbus-launch --config-file $PREFIX/share/dbus-1/system.conf UPOWER_CONF_FILE_NAME=$PREFIX/etc/UPower/UPower.conf $PREFIX/libexec/upowerd -d & gnome-session --session=minimal \$@ EOF chmod +x "$PREFIX/bin/gnome-session-minimal" fi fi } # add the basic details into a config file function print_basic_details() { local net_condition local country net_condition="$(getprop gsm.network.type)" country="$(getprop gsm.sim.operator.iso-country)" if [[ -f "$CONFIG_FILE" ]]; then check_and_backup "$CONFIG_FILE" fi cat <"$CONFIG_FILE" #################################### ########## Termux Desktop ########## #################################### ######################## # -:Device Details:- # ######################## # # Termux Version: ${TERMUX_VERSION}-${TERMUX_APK_RELEASE} # Device Model: $MODEL # Android Version: $ANDROID_VERSION # Free Space: $FREE_SPACE # Total Ram: $TOTAL_RAM # Architecture: $APP_ARCH # System CPU Architecture: $SUPPORTED_ARCH # Processor: $PROCESSOR_BRAND_NAME $PROCESSOR_NAME # GPU: $GPU_NAME # Network Condition: $net_condition # Country: $country # ######################## ##### Please don't modify this file otherwise some functions won't work ##### EOF } function add_installer() { if [[ ! -e "$PREFIX/bin/setup-termux-desktop" ]]; then print_msg "Adding setup-termux-desktop installer to bin" download_file "$PREFIX/bin/setup-termux-desktop" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/setup-termux-desktop" chmod +x "$PREFIX/bin/setup-termux-desktop" fi } ######################################################################### # # Update Task # ######################################################################### # check for the changes in the installer file function check_for_update_and_update_installer() { if [[ -e "$PREFIX/bin/setup-termux-desktop" ]]; then banner print_msg "Checking for update..." echo check_and_create_directory "$TERMUX_DESKTOP_PATH" local current_script_hash local update_installer current_script_hash=$(curl -sL https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/setup-termux-desktop | sha256sum | cut -d ' ' -f 1) local local_script_hash local_script_hash=$(basename "$(sha256sum "$PREFIX/bin/setup-termux-desktop" | cut -d ' ' -f 1)") if [[ "$local_script_hash" != "$current_script_hash" ]]; then confirmation_y_or_n "You are using an old installer. Do you want to update it to the latest version" update_installer if [[ "$update_installer" == "y" ]]; then check_and_create_directory "$PREFIX/etc/termux-desktop" mv "$PREFIX/bin/setup-termux-desktop" "$PREFIX/etc/termux-desktop/" check_and_backup "$PREFIX/etc/termux-desktop/setup-termux-desktop" add_installer add_common_function unset local_script_hash local new_local_script_hash new_local_script_hash=$(basename "$(sha256sum "$PREFIX/bin/setup-termux-desktop" | cut -d ' ' -f 1)") if [[ "$new_local_script_hash" == "$current_script_hash" ]]; then print_msg "Installer updated successfully" check_and_delete "$TERMUX_DESKTOP_PATH/skip_update_checkup" exit 0 else print_msg "Failed to update the installer" exit 0 fi elif [[ "$update_installer" == "n" ]]; then print_msg "Keeping the old installer" check_and_create_directory "$TERMUX_DESKTOP_PATH" touch "$TERMUX_DESKTOP_PATH/skip_update_checkup" exit 0 fi else print_msg "${BOLD}Great, you are using the latest installer" fi fi } function check_installer_status() { if [[ -e "$PREFIX/bin/setup-termux-desktop" ]]; then if [[ ! -e "$TERMUX_DESKTOP_PATH/skip_update_checkup" ]]; then check_for_update_and_update_installer else print_msg "${BOLD}Update check skipped" print_msg "${BOLD}Use ${C}--update ${G}to force update check" fi fi } function check_for_appstore_update() { print_msg "Checking for appstore updates..." echo appstore --update } ######################################################################### # # Reset Changes # ######################################################################### function reset_changes() { if [[ ! -e "$CONFIG_FILE" ]]; then echo -e "${C} It looks like you haven't installed the desktop yet.\n Please install the desktop first.${NC}" exit 1 else read_conf banner print_msg "Removing $de_name Config..." set_config_dir check_and_delete "${config_dirs[@]}" get_shellrc_path if [[ "$terminal_utility_setup_answer" == "y" ]]; then check_and_delete "$PREFIX/etc/motd.sh $HOME/.termux $HOME/.fonts/font.ttf $HOME/.termux/colors.properties" termux-reload-settings check_and_restore "$PREFIX/etc/motd" termux-reload-settings check_and_restore "$PREFIX/etc/motd-playstore" check_and_restore "$PREFIX/etc/motd.sh" termux-reload-settings check_and_restore "$HOME/.termux/colors.properties" # shellcheck disable=SC2164 cd /data/data/com.termux/files/usr/share/zsh/site-functions check_and_delete "_add2menu _distro _setup-termux-desktop _tx11start _tx11stop _vncstart _vncstop" # shellcheck disable=SC2164 cd /data/data/com.termux/files/usr/share/bash-completion/completions check_and_delete "add2menu distro setup-termux-desktop tx11start tx11stop vncstart vncstop" # shellcheck disable=SC2164 cd "$HOME" if grep -q "motd.sh$" "$PREFIX/etc/termux-login.sh"; then sed -i "s|.*motd\.sh$|# |" "$PREFIX/etc/termux-login.sh" termux-reload-settings fi rm "$PREFIX/share/applications/wine-*.desktop" >/dev/null 2>&1 check_and_delete "$TERMUX_DESKTOP_PATH" check_and_delete "$PREFIX/bin/tx11start $PREFIX/bin/tx11stop $PREFIX/bin/vncstop $PREFIX/bin/vncstart $PREFIX/bin/gui $PREFIX/bin/pdrun" fi check_and_delete "$HOME/Music" check_and_delete "$HOME/Downloads" check_and_delete "$HOME/Desktop" check_and_delete "$HOME/Pictures" check_and_delete "$HOME/Videos" if [[ "$shell_name" == "zsh" ]]; then chsh -s bash check_and_delete "$HOME/.oh-my-zsh" fi check_and_delete "$shell_rc_file" check_and_restore "$shell_rc_file" print_success "${BOLD}Reset successful. Now restart Termux." fi } ######################################################################### # # Call Functions # ######################################################################### check_termux detact_package_manager if [[ -z "$1" ]] || [[ "$1" == "--install" ]] || [[ "$1" == "-i" ]]; then check_installer_status "$1" fi current_path=$(pwd) get_termux_arch function install_termux_desktop() { banner update_sys cleanup_cache termux-wake-lock install_required_packages recheck_basic_packages if [[ "$1" != "--local-config" && "$1" != "--config" && "$1" != "-config" ]]; then print_recomended_msg fi if [[ "$1" != "--local-config" && "$1" != "--config" && "$1" != "-config" ]]; then questions_install_type if [[ "$install_type_answer" == "1" ]]; then if [[ "$distro_add_answer" == "y" ]]; then distro_questions fi if [[ "$enable_hw_acc" == "y" ]]; then setup_device_gpu_model hw_questions fi fi fi if [[ "$1" == "--local-config" ]] || [[ "$1" == "--config" ]] || [[ "$1" == "-config" ]]; then download_file "${current_path}/styles.md" "https://raw.githubusercontent.com/sabamdarif/termux-desktop/refs/heads/main/docs/${de_name}_styles.md" style_name=$(grep -oP "^## $style_answer\..+?(?=(\n## \d+\.|\Z))" "${current_path}/styles.md" | sed -e "s/^## $style_answer\. //" -e "s/:$//" -e 's/^[[:space:]]*//;s/[[:space:]]*$//') check_and_delete "${current_path}/styles.md" fi print_conf_info check_and_create_directory "${TERMUX_DESKTOP_PATH}" log_debug "$CONFIG_FILE" print_basic_details setup_necessary_permissions setup_shell setup_fonts install_desktop browser_installer ide_installer media_player_installer photo_editor_installer setup_wine if [[ "$style_answer" == "0" ]]; then banner print_msg "${BOLD}Configuring Stock $de_name Style..." echo print_to_config "style_answer" ext_setup_for_stock else setup_config fi ext_wall_setup banner add_common_function distro_container_setup gui_launcher terminal_utility_setup if [[ "$selected_distro_type" == "proot" ]]; then install_termux_desktop_appstore fi add_to_autostart check_desktop_process install_fm_tools add_auto_completion some_fixes cleanup_cache termux-wake-unlock add_installer notes log_debug "$(cat $CONFIG_FILE)" delete_installer_file } function show_help() { echo -e " --debug to create a log file -i,--install to start installation -r,--remove to remove termux desktop -c,--change to change some previous configuration -ri,--reinstall to reinstall some previously install stuff --reset to reset all changes made by this script without uninstalling any package --local-config,-config to start the installation from pre made config file -h,--help to show help " } function show_change_help() { echo "options you can use with --change" echo -e " style to change installed style pd,distro to change installed linux distro container hw,hwa to change hardware acceleration method autostart to change autostart behaviour display to change termux:x11 display port de,wm to switch between diffreent desktop environment or window manager h,help to show help example uses : --change style " } function show_reinstall_help() { echo -e " options you can use with --reinstall icons to reinstall icons pack themes to reinstall themes pack config to reinstall config h,help to show help example uses : --reinstall icons example uses : --reinstall icons,themes...etc to reinstall them at once " } if [[ $1 == "--debug" ]]; then trap debug_msg debug shift fi case $1 in --remove | -r | --uninstall) remove_termux_desktop ;; --install | -i | in) install_termux_desktop "$1" ;; --change | -c) case $2 in style) # shellcheck disable=SC2034 CALL_FROM_CHANGE_STYLE=true change_style ;; distro | pd) # shellcheck disable=SC2034 CALL_FROM_CHANGE_DISTRO=true change_distro ;; hw | hwa) change_hw ;; autostart) change_autostart ;; display) change_display ;; de | wm | desktop | winm | wim) change_de ;; h | help | -h | --help) show_change_help ;; *) print_failed "${BOLD} Invalid option: ${C}$2" print_msg "Use --change help to show help" ;; esac ;; --reinstall | -ri) IFS=',' read -ra OPTIONS <<<"$2" for option in "${OPTIONS[@]}"; do case $option in icons) reinstall_icons ;; themes) reinstall_themes ;; config) reinstall_config ;; h | help | -h | --help) show_reinstall_help exit ;; *) print_failed "${BOLD} Invalid option: ${C}$option" print_msg "Use --reinstall help to show help" ;; esac done ;; --update) check_for_update_and_update_installer "$1" check_for_appstore_update ;; --help | -h) show_help ;; --reset) reset_changes ;; --local-config | --config | -config) print_recomended_msg load_local_config "$2" install_termux_desktop "$1" ;; *) if [[ -n "$1" ]]; then print_failed "${BOLD} Invalid option: ${C}$1" show_help else install_termux_desktop "$1" fi if [[ -z "$PREFIX" && "$PREFIX" != *"/com.termux/"* ]]; then print_failed "${BOLD}Please run it inside termux${NC}" exit 0 fi ;; esac