From d64ff0af9cc01124bf198ca0ffcf34c2b66b78f1 Mon Sep 17 00:00:00 2001 From: Prashant Adhikari Date: Mon, 7 Sep 2026 15:07:23 +0545 Subject: [PATCH 1/2] feat: add GNOME Wayland support via Mutter and gnome-remote-desktop - Add backend detection to route between X11 and GNOME Wayland - Implement virtual display extension using Mutter DisplayConfig - Integrate gnome-remote-desktop for Wayland VNC streaming - Harden module inclusion guards and remove redundant comments - Clarify quick start commands across CLI, installer, and README --- README.md | 29 +++-- config/default.conf | 2 +- floweave.sh | 89 ++++---------- install.sh | 5 +- modules/config-manager.sh | 64 ++-------- modules/dependency-installer.sh | 149 ++++++++++++++--------- modules/display-backend.sh | 68 +++++++++++ modules/display-manager.sh | 84 ++++++------- modules/system-checker.sh | 183 +++++++++++++---------------- modules/ui-helpers.sh | 64 ++-------- modules/vnc-server.sh | 151 +++++++++++++++--------- modules/wayland-display-manager.sh | 96 +++++++++++++++ 12 files changed, 530 insertions(+), 454 deletions(-) create mode 100644 modules/display-backend.sh create mode 100644 modules/wayland-display-manager.sh diff --git a/README.md b/README.md index b1df54c..1c504c7 100644 --- a/README.md +++ b/README.md @@ -17,16 +17,19 @@ ## ✨ Features -- **Wireless Display:** Extend your Xorg desktop to any device using VNC. +- **Wireless Display:** Extend your Linux desktop to any device using VNC. +- **Display Server Support:** Works on both Xorg (X11) and GNOME Wayland. - **Configurable Output:** Adjust resolution, position, and scaling as needed. - **Interactive CLI:** Clean, intuitive terminal interface for managing sessions. - **No Cables Required:** Works seamlessly over your local WiFi network. ## πŸ“‹ Requirements -- Linux with an **Xorg (X11)** session β€” Wayland is not supported +- Linux with an **Xorg (X11)** session or **GNOME Wayland** session (GNOME 40+ with Mutter) + > [!NOTE] + > Wayland support is currently limited to GNOME. Other Wayland compositors (such as KDE Plasma, Hyprland, and Sway) are not supported. - Both your laptop and second device on the **same WiFi network** -- A **VNC client** app on your second device β€” e.g. [AVNC](https://github.com/gujjwal00/avnc) (Android), [RealVNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) (iOS/Android/desktop) +- A **VNC client** app on your second device (such as [AVNC](https://github.com/gujjwal00/avnc) for Android, or [RealVNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) for iOS/Android/desktop) ## πŸš€ Installation @@ -47,12 +50,14 @@ > The installer automatically handles all required dependencies. -3. **Launch Floweave:** +3. **Start Floweave:** ```bash - floweave + floweave --start ``` + Or run `floweave` to open the interactive dashboard and select **Start Floweave**. + 4. **Connect your device:** Open your VNC client app, enter the IP address and port shown by Floweave (e.g. `192.168.1.x:5900`), and connect. > [!IMPORTANT] @@ -76,13 +81,13 @@ From here, you can start/stop the service, configure settings, and view connecti For fast operations and scripting: -| Command | Description | -| :----------------- | :--------------------------------------------- | -| `floweave start` | Start the virtual display and VNC server | -| `floweave stop` | Stop the server and remove the virtual display | -| `floweave config` | Open the configuration wizard | -| `floweave help` | Show help information | -| `floweave version` | Display current version | +| Command | Description | +| :----------------------------- | :--------------------------------------------- | +| `floweave --start` / `start` | Start the virtual display and VNC server | +| `floweave --stop` / `stop` | Stop the server and remove the virtual display | +| `floweave --config` / `config` | Open the configuration wizard | +| `floweave --help` / `help` | Show help information | +| `floweave --version` | Display current version | --- diff --git a/config/default.conf b/config/default.conf index 5a4cc2e..c2ed4d9 100644 --- a/config/default.conf +++ b/config/default.conf @@ -28,7 +28,7 @@ password= [system] # Floweave version -version=1.0.0 +version= # Last configuration update timestamp # Automatically updated by Floweave diff --git a/floweave.sh b/floweave.sh index ac48516..7064a3f 100755 --- a/floweave.sh +++ b/floweave.sh @@ -1,22 +1,5 @@ #!/bin/bash -################################################################################ -# Floweave - Main CLI Entry Point -# -# Transform your Android device into an extended display for Linux -# using VNC over WiFi (no USB/ADB required) -# -# Functions: -# - prompt_configuration() -# - menu_start_floweave() -# - menu_stop_floweave() -# - menu_configure_settings() -# - menu_help() -# - cleanup() -# - main() -################################################################################ - -# Script metadata -# Read version from VERSION file if it exists, otherwise default + SCRIPT_PATH="${BASH_SOURCE[0]}" if [[ -L "$SCRIPT_PATH" ]]; then SCRIPT_PATH="$(readlink -f "$SCRIPT_PATH")" @@ -29,13 +12,14 @@ else FLOWEAVE_VERSION="unknown" fi -# Source all modules MODULES=( "modules/ui-helpers.sh" "modules/system-checker.sh" "modules/dependency-installer.sh" "modules/config-manager.sh" + "modules/display-backend.sh" "modules/display-manager.sh" + "modules/wayland-display-manager.sh" "modules/vnc-server.sh" ) @@ -49,22 +33,16 @@ for module in "${MODULES[@]}"; do fi done -# Global CONFIG associative array declare -A CONFIG -# cleanup() cleanup() { - # NOTE: This function ONLY exits the program - it does NOT stop the VNC server - # VNC server runs as a background daemon and persist after program exit echo "" show_info "Exiting Floweave..." exit 0 } -# Set up signal handlers trap cleanup SIGINT SIGTERM -# prompt_configuration() prompt_configuration() { show_box "CONFIGURATION" echo "" @@ -142,13 +120,11 @@ prompt_configuration() { return 0 } -# menu_start_floweave() menu_start_floweave() { clear show_box "START FLOWEAVE" echo "" - # Check if already running if is_running; then show_warning "Service is already active." echo "" @@ -157,20 +133,12 @@ menu_start_floweave() { return 0 fi - - # STEP 1: Verify system requirements (combined check) show_loading "Verifying system requirements" 1 - # Check display server silently - if ! check_display_server &>/dev/null; then - echo "" - echo -e " ${RED}${BOLD}Γ— CRITICAL: Xorg Display Server Required${RESET}" - echo -e "${DIM} ──────────────────────────────────────────────────${RESET}" - echo -e " Floweave requires an ${BOLD}Xorg (X11)${RESET} session." - echo -e " Your system is currently running Wayland." + local display_check_output + if ! display_check_output=$(check_display_server 2>&1); then echo "" - echo -e " ${CYAN}Please switch to an Xorg session to continue.${RESET}" - echo -e " ${DIM}Refer to the 'Help & Usage Guide' for more information.${RESET}" + echo "$display_check_output" echo "" return 1 fi @@ -283,20 +251,16 @@ menu_stop_floweave() { show_box "STOP FLOWEAVE" echo "" - # Check if running if ! is_running; then show_warning "Service is already stopped. No action taken." return 0 fi - # Load configuration load_config - # Stop VNC server with loading animation show_loading "Stopping VNC server" 1 stop_vnc_server &>/dev/null - # Remove virtual display with loading animation show_loading "Removing virtual display" 1 remove_virtual_display &>/dev/null @@ -305,16 +269,13 @@ menu_stop_floweave() { return 0 } -# menu_configure_settings() menu_configure_settings() { clear show_box "CONFIGURE SETTINGS" echo "" - # Load current configuration load_config - # 1. Display Current Settings echo -e " ${GREEN}${BOLD}CURRENT CONFIGURATION${RESET}" echo -e "${DIM} ──────────────────────────────────────────────────${RESET}" printf " %-18s ${BOLD}%s${RESET}\n" "Resolution:" "${CONFIG[display_width]}x${CONFIG[display_height]}" @@ -330,8 +291,6 @@ menu_configure_settings() { echo -e " ${GREEN}${BOLD}Enter new values below (press Enter to keep current)${RESET}" echo "" - # 2. Edit Form - # Display Resolution echo -e " ${BLUE}${BOLD}Display Resolution${RESET}" echo -ne " ${ARROW_RIGHT} Width [${CONFIG[display_width]}]: " read -r width @@ -345,25 +304,22 @@ menu_configure_settings() { CONFIG[display_height]="$height" echo "" - # Display Position echo -e " ${BLUE}${BOLD}Display Position${RESET}" echo -e " ${DIM}(Options: right(r), left(l), top(t), bottom(b))${RESET}" echo -ne " ${ARROW_RIGHT} Direction [r]: " read -r position position="${position:-${CONFIG[display_position]}}" - # Convert single letter to full word case "$position" in r|R) CONFIG[display_position]="right" ;; l|L) CONFIG[display_position]="left" ;; t|T) CONFIG[display_position]="above" ;; b|B) CONFIG[display_position]="below" ;; right|left|above|below) CONFIG[display_position]="$position" ;; - *) ;; # Keep current if invalid + *) ;; esac echo "" - # Security echo -e " ${BLUE}${BOLD}Security${RESET}" echo -ne " ${ARROW_RIGHT} VNC Port [${CONFIG[vnc_port]}]: " read -r port @@ -378,19 +334,16 @@ menu_configure_settings() { CONFIG[vnc_password]="$new_password" fi - # Update timestamp CONFIG[system_last_updated]=$(date +"%Y-%m-%d %H:%M:%S") echo "" - # Validate configuration if ! validate_config; then echo "" show_warning "Configuration not saved - please try again with valid values" return 1 fi - # Save configuration if ! save_config; then show_error "Failed to save configuration" return 1 @@ -398,7 +351,6 @@ menu_configure_settings() { echo -e " ${GREEN}${BOLD}${CHECK_MARK} Configuration updated successfully${RESET}" - # Warn if running if is_running; then echo "" echo -e " ${YELLOW}⚠ Note: Restart Floweave for changes to take effect${RESET}" @@ -406,7 +358,7 @@ menu_configure_settings() { return 0 } -# menu_help() + menu_help() { clear show_box "FLOWEAVE HELP & USAGE GUIDE" @@ -414,17 +366,17 @@ menu_help() { # What is Floweave echo -e "${GREEN}${BOLD}${ARROW_RIGHT} WHAT IS FLOWEAVE?${RESET}" - echo " Floweave is a Linux CLI tool that creates a virtual Xorg display and streams" - echo " it over VNC, allowing any device with a VNC viewerβ€”Android, iOS, Windows," - echo " macOS, or another computerβ€”to act as an extended monitor. It uses xrandr and" - echo " x11vnc, requires an Xorg session (not Wayland), and enables wireless screen" + echo " Floweave is a Linux CLI tool that creates a virtual display and streams" + echo " it over VNC, allowing any device with a VNC viewer (Android, iOS, Windows," + echo " macOS, or another computer) to act as an extended monitor. It supports" + echo " both Xorg (X11) and GNOME Wayland sessions, enabling wireless screen" echo " extension without USB or ADB." echo "" # Requirements echo -e "${GREEN}${BOLD}${ARROW_RIGHT} REQUIREMENTS:${RESET}" - echo " β€’ Xorg display server (not Wayland)" - echo " β€’ xrandr, x11vnc installed" + echo " β€’ Xorg (X11) or GNOME Wayland session" + echo " β€’ X11: xrandr, x11vnc | Wayland: gnome-remote-desktop" echo " β€’ Any device with a VNC viewer app (Android, iOS, Windows, macOS, Linux, etc.)" echo " β€’ Both devices on same WiFi network" echo "" @@ -437,9 +389,9 @@ menu_help() { # Quick Start echo -e "${GREEN}${BOLD}${ARROW_RIGHT} QUICK START:${RESET}" - echo " 1. Run 'Start Floweave' to configure and start the VNC server" + echo " 1. Run 'floweave --start' (or select 'Start Floweave' from the interactive menu)" echo " 2. Connect using your device's VNC viewer to the IP address and port displayed" - echo " 3. Use 'Stop Floweave' when done to clean up the virtual display" + echo " 3. Run 'floweave --stop' (or select 'Stop Floweave') when done to clean up" echo "" # CLI Usage @@ -454,18 +406,17 @@ menu_help() { echo -e " ${BOLD}floweave --version${RESET} Show version information" echo "" - # Troubleshooting + # Troubleshooting echo -e "${GREEN}${BOLD}${ARROW_RIGHT} TROUBLESHOOTING:${RESET}" echo " β€’ Connection refused: Check firewall, verify same WiFi network" - echo " β€’ Display not appearing: Verify Xorg (not Wayland), check xrandr output" + echo " β€’ Display arrangement: On GNOME Wayland, arrange displays in Settings > Displays" echo " β€’ Performance issues: Reduce resolution, check network bandwidth" - echo " β€’ Wayland detected: Log out and select 'Xorg' or 'X11' session at login," - echo " or consult online documentation for your specific Linux distribution." + echo " β€’ Unsupported compositor: On Wayland, currently GNOME (Mutter) is supported." + echo " For other compositors, switch to an Xorg (X11) session." return 0 } -# main() main() { # Parse command-line arguments case "${1:-}" in diff --git a/install.sh b/install.sh index b6943f2..4d672a9 100755 --- a/install.sh +++ b/install.sh @@ -24,7 +24,7 @@ BIN_PATH="$BIN_DIR/floweave" # Custom Installer Header show_installer_header() { - clear + clear 2>/dev/null || true echo -e "${DIM}β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”${RESET}" echo -e "${DIM}β”‚${RESET} ${DIM}β”‚${RESET}" echo -e "${DIM}β”‚${RESET} ${GREEN}β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—${RESET} ${DIM}β”‚${RESET}" @@ -165,7 +165,8 @@ if [[ "$PATH_UPDATED" == true ]] && [[ -n "$SHELL_PROFILE" ]]; then fi show_box "Quick Start" -echo -e " β€’ Run ${CYAN}${BOLD}floweave${RESET} to start the menu" +echo -e " β€’ Run ${CYAN}${BOLD}floweave --start${RESET} to start the service" +echo -e " β€’ Run ${CYAN}${BOLD}floweave${RESET} to launch the interactive menu" echo -e " β€’ Run ${CYAN}${BOLD}floweave --help${RESET} for CLI usage" echo "" echo -e " ${DIM}(You can now safely delete this installer folder)${RESET}" diff --git a/modules/config-manager.sh b/modules/config-manager.sh index ab25f05..5b29c1e 100755 --- a/modules/config-manager.sh +++ b/modules/config-manager.sh @@ -1,18 +1,8 @@ #!/bin/bash -################################################################################ -# Floweave - Configuration Manager Module -# -# Functions: -# - read_ini_value() -# - write_ini_value() -# - is_configured() -# - is_running() -# - load_config() -# - save_config() -# - validate_config() -################################################################################ - -# Configuration paths (use environment variables if set, otherwise use defaults) + +[[ -n "${FLOWEAVE_CONFIG_MANAGER_LOADED}" ]] && return 0 +FLOWEAVE_CONFIG_MANAGER_LOADED=1 + FLOWEAVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" FLOWEAVE_CONFIG_DIR="${FLOWEAVE_CONFIG_DIR:-${HOME}/.config/floweave}" FLOWEAVE_CONFIG_FILE="${FLOWEAVE_CONFIG_FILE:-${FLOWEAVE_CONFIG_DIR}/config.ini}" @@ -20,10 +10,8 @@ FLOWEAVE_PID_FILE="${FLOWEAVE_PID_FILE:-${FLOWEAVE_CONFIG_DIR}/floweave.pid}" FLOWEAVE_DISPLAY_FILE="${FLOWEAVE_DISPLAY_FILE:-${FLOWEAVE_CONFIG_DIR}/display.name}" FLOWEAVE_DEFAULT_CONF="${FLOWEAVE_DIR}/config/default.conf" -# Global configuration variables declare -A CONFIG -# read_ini_value() read_ini_value() { local file="$1" local section="$2" @@ -80,17 +68,14 @@ read_ini_value() { fi } -# write_ini_value() write_ini_value() { local file="$1" local section="$2" local key="$3" local value="$4" - # Create config directory if it doesn't exist mkdir -p "$(dirname "$file")" - # If file doesn't exist, create it with the section and key if [[ ! -f "$file" ]]; then echo "[$section]" > "$file" echo "$key=$value" >> "$file" @@ -102,11 +87,9 @@ write_ini_value() { local key_found=0 while IFS= read -r line || [[ -n "$line" ]]; do - # Check for section header if [[ "$line" =~ ^\[(.+)\]$ ]]; then local current_section="${BASH_REMATCH[1]}" - # If we were in the target section but didn't find the key, add it if [[ $in_section -eq 1 && $key_found -eq 0 ]]; then echo "$key=$value" >> "$temp_file" key_found=1 @@ -122,7 +105,6 @@ write_ini_value() { continue fi - # If in the target section, check if this is the key to update if [[ $in_section -eq 1 && "$line" =~ ^([^=]+)= ]]; then local current_key="${BASH_REMATCH[1]}" current_key=$(echo "$current_key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') @@ -137,13 +119,11 @@ write_ini_value() { echo "$line" >> "$temp_file" done < "$file" - # If we were in the target section at EOF but didn't find the key, add it if [[ $in_section -eq 1 && $key_found -eq 0 ]]; then echo "$key=$value" >> "$temp_file" key_found=1 fi - # If section wasn't found, add it with the key if [[ $key_found -eq 0 ]]; then echo "" >> "$temp_file" echo "[$section]" >> "$temp_file" @@ -154,14 +134,11 @@ write_ini_value() { return 0 } -# is_configured() is_configured() { - # Check if config file exists and has required values if [[ ! -f "$FLOWEAVE_CONFIG_FILE" ]]; then return 1 fi - # Check for required configuration values local width=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "width") local height=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "height") local position=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "position") @@ -173,45 +150,40 @@ is_configured() { return 0 } -# is_running() is_running() { - # Check if PID file exists if [[ ! -f "$FLOWEAVE_PID_FILE" ]]; then return 1 fi - # Read PID from file local pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) - # Check if PID is valid if [[ -z "$pid" || ! "$pid" =~ ^[0-9]+$ ]]; then return 1 fi - # Check if process is running if ps -p "$pid" > /dev/null 2>&1; then - # Verify it's actually x11vnc - if ps -p "$pid" -o comm= | grep -q "x11vnc"; then + local comm + comm=$(ps -p "$pid" -o comm= 2>/dev/null) + if [[ "$comm" =~ x11vnc ]]; then return 0 + elif [[ "$comm" =~ gnome-remote ]]; then + if grdctl status 2>/dev/null | grep -A 3 "VNC:" | grep -q "Status: enabled"; then + return 0 + fi fi fi - # PID file exists but process is not running - clean up stale PID file rm -f "$FLOWEAVE_PID_FILE" return 1 } -# load_config() load_config() { - # Create config directory if it doesn't exist mkdir -p "$FLOWEAVE_CONFIG_DIR" - # If config file doesn't exist, create it from default template if [[ ! -f "$FLOWEAVE_CONFIG_FILE" ]]; then if [[ -f "$FLOWEAVE_DEFAULT_CONF" ]]; then cp "$FLOWEAVE_DEFAULT_CONF" "$FLOWEAVE_CONFIG_FILE" else - # Fallback: create minimal config if template is missing cat > "$FLOWEAVE_CONFIG_FILE" << 'EOF' [display] width=1280 @@ -230,28 +202,23 @@ EOF fi fi - # Load configuration values into CONFIG associative array CONFIG[display_width]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "width" "1280") CONFIG[display_height]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "height" "720") CONFIG[display_position]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "position" "right") CONFIG[display_monitor]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "monitor" "") CONFIG[vnc_port]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "vnc" "port" "5900") CONFIG[vnc_password]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "vnc" "password" "") - CONFIG[system_version]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "system" "version" "${FLOWEAVE_VERSION:-1.0.0}") + CONFIG[system_version]="${FLOWEAVE_VERSION:-$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "system" "version" "1.0.0")}" CONFIG[system_last_updated]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "system" "last_updated" "") return 0 } -# save_config() save_config() { - # Create config directory if it doesn't exist mkdir -p "$FLOWEAVE_CONFIG_DIR" - # Update last_updated timestamp CONFIG[system_last_updated]=$(date '+%Y-%m-%d %H:%M:%S') - # Write all configuration values to file write_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "width" "${CONFIG[display_width]}" write_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "height" "${CONFIG[display_height]}" write_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "position" "${CONFIG[display_position]}" @@ -264,37 +231,30 @@ save_config() { return 0 } -# validate_config() validate_config() { local errors=0 - # Validate display width if [[ ! "${CONFIG[display_width]}" =~ ^[0-9]+$ ]] || [[ ${CONFIG[display_width]} -lt 640 ]] || [[ ${CONFIG[display_width]} -gt 3840 ]]; then show_error "Invalid display width: ${CONFIG[display_width]} (must be 640-3840)" errors=$((errors + 1)) fi - # Validate display height if [[ ! "${CONFIG[display_height]}" =~ ^[0-9]+$ ]] || [[ ${CONFIG[display_height]} -lt 480 ]] || [[ ${CONFIG[display_height]} -gt 2160 ]]; then show_error "Invalid display height: ${CONFIG[display_height]} (must be 480-2160)" errors=$((errors + 1)) fi - # Validate display position if [[ ! "${CONFIG[display_position]}" =~ ^(left|right|above|below)$ ]]; then show_error "Invalid display position: ${CONFIG[display_position]} (must be: left, right, above, below)" errors=$((errors + 1)) fi - # Validate VNC port if [[ ! "${CONFIG[vnc_port]}" =~ ^[0-9]+$ ]] || [[ ${CONFIG[vnc_port]} -lt 5900 ]] || [[ ${CONFIG[vnc_port]} -gt 5999 ]]; then show_error "Invalid VNC port: ${CONFIG[vnc_port]} (must be 5900-5999)" errors=$((errors + 1)) fi - # Validate VNC password (optional - can be empty for passwordless VNC) if [[ -n "${CONFIG[vnc_password]}" ]] && [[ ${#CONFIG[vnc_password]} -gt 8 ]]; then - # Validate VNC password length (x11vnc supports max 8 characters) show_warning "VNC password truncated to 8 characters (x11vnc limitation)" CONFIG[vnc_password]="${CONFIG[vnc_password]:0:8}" fi diff --git a/modules/dependency-installer.sh b/modules/dependency-installer.sh index 1d10ebe..e9a2ef4 100755 --- a/modules/dependency-installer.sh +++ b/modules/dependency-installer.sh @@ -1,32 +1,20 @@ #!/bin/bash -################################################################################ -# Floweave - Dependency Installer Module -# -# Functions: -# - detect_distro() -# - check_dependencies_silent() -# - install_dependencies() -################################################################################ - -# Source UI helpers for message functions (if not already loaded) + if ! command -v show_info &> /dev/null; then SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/ui-helpers.sh" fi -# detect_distro() detect_distro() { show_info "Detecting Linux distribution..." >&2 if [[ -f /etc/os-release ]]; then - # Source the os-release file to get distribution info source /etc/os-release DISTRO="${ID}" VERSION_ID="${VERSION_ID}" show_success "Detected: ${NAME} ${VERSION_ID}" >&2 - # Determine package manager based on distribution case "${DISTRO}" in ubuntu|debian|linuxmint|pop|elementary) PKG_MANAGER="apt" @@ -55,7 +43,6 @@ detect_distro() { ;; esac - # Echo clean distro name for capture echo "${DISTRO}" return 0 else @@ -65,14 +52,27 @@ detect_distro() { fi } -# check_dependencies_silent() check_dependencies_silent() { MISSING_DEPS=() - local all_deps=( - "xrandr:x11-xserver-utils" - "cvt:x11-xserver-utils" - "x11vnc:x11vnc" - ) + + local module_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + source "$module_dir/display-backend.sh" + detect_display_backend + + local all_deps=() + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + all_deps=( + "grdctl:gnome-remote-desktop" + "gdbus:glib" + "gsettings:glib" + ) + else + all_deps=( + "xrandr:x11-xserver-utils" + "cvt:x11-xserver-utils" + "x11vnc:x11vnc" + ) + fi for dep_info in "${all_deps[@]}"; do local cmd="${dep_info%%:*}" @@ -90,51 +90,84 @@ check_dependencies_silent() { fi } -# install_dependencies() install_dependencies() { - # show_info "Installing Floweave dependencies..." - - # Detect distribution if not already done if [[ -z "${PKG_MANAGER}" ]]; then detect_distro || return 1 fi + local module_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + source "$module_dir/display-backend.sh" + detect_display_backend + echo "" - case "${PKG_MANAGER}" in - apt) - echo -e "${GREEN}Updating package lists...${RESET}" - sudo apt update || return 1 - echo "" - echo -e "${GREEN}Installing packages: x11vnc, x11-xserver-utils...${RESET}" - sudo apt install -y x11vnc x11-xserver-utils || return 1 - ;; - dnf) - show_info "Installing packages: x11vnc, xorg-x11-server-utils" - sudo dnf install -y x11vnc xorg-x11-server-utils || return 1 - ;; - yum) - show_info "Enabling EPEL repository..." - sudo yum install -y epel-release || return 1 - show_info "Installing packages: x11vnc, xorg-x11-server-utils" - sudo yum install -y x11vnc xorg-x11-server-utils || return 1 - ;; - pacman) - show_info "Installing packages: x11vnc, xorg-xrandr" - sudo pacman -S --noconfirm x11vnc xorg-xrandr || return 1 - ;; - zypper) - show_info "Installing packages: x11vnc, xrandr" - sudo zypper install -y x11vnc xrandr || return 1 - ;; - *) - show_error "Unsupported package manager: ${PKG_MANAGER}" - show_info "Please install the following packages manually:" - echo " - x11vnc (VNC server)" - echo " - xrandr (display management)" - return 1 - ;; - esac + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + case "${PKG_MANAGER}" in + apt) + echo -e "${GREEN}Updating package lists...${RESET}" + sudo apt update || return 1 + echo "" + echo -e "${GREEN}Installing package: gnome-remote-desktop...${RESET}" + sudo apt install -y gnome-remote-desktop || return 1 + ;; + dnf) + show_info "Installing package: gnome-remote-desktop" + sudo dnf install -y gnome-remote-desktop || return 1 + ;; + yum) + show_info "Installing package: gnome-remote-desktop" + sudo yum install -y gnome-remote-desktop || return 1 + ;; + pacman) + show_info "Installing package: gnome-remote-desktop" + sudo pacman -S --noconfirm gnome-remote-desktop || return 1 + ;; + zypper) + show_info "Installing package: gnome-remote-desktop" + sudo zypper install -y gnome-remote-desktop || return 1 + ;; + *) + show_error "Unsupported package manager: ${PKG_MANAGER}" + show_info "Please install gnome-remote-desktop manually." + return 1 + ;; + esac + else + case "${PKG_MANAGER}" in + apt) + echo -e "${GREEN}Updating package lists...${RESET}" + sudo apt update || return 1 + echo "" + echo -e "${GREEN}Installing packages: x11vnc, x11-xserver-utils...${RESET}" + sudo apt install -y x11vnc x11-xserver-utils || return 1 + ;; + dnf) + show_info "Installing packages: x11vnc, xorg-x11-server-utils" + sudo dnf install -y x11vnc xorg-x11-server-utils || return 1 + ;; + yum) + show_info "Enabling EPEL repository..." + sudo yum install -y epel-release || return 1 + show_info "Installing packages: x11vnc, xorg-x11-server-utils" + sudo yum install -y x11vnc xorg-x11-server-utils || return 1 + ;; + pacman) + show_info "Installing packages: x11vnc, xorg-xrandr" + sudo pacman -S --noconfirm x11vnc xorg-xrandr || return 1 + ;; + zypper) + show_info "Installing packages: x11vnc, xrandr" + sudo zypper install -y x11vnc xrandr || return 1 + ;; + *) + show_error "Unsupported package manager: ${PKG_MANAGER}" + show_info "Please install the following packages manually:" + echo " - x11vnc (VNC server)" + echo " - xrandr (display management)" + return 1 + ;; + esac + fi return 0 } diff --git a/modules/display-backend.sh b/modules/display-backend.sh new file mode 100644 index 0000000..becdb75 --- /dev/null +++ b/modules/display-backend.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +[[ -n "${_FLOWEAVE_DISPLAY_BACKEND_LOADED}" ]] && return 0 +_FLOWEAVE_DISPLAY_BACKEND_LOADED=1 + +if ! command -v show_info &> /dev/null; then + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + source "${SCRIPT_DIR}/ui-helpers.sh" +fi + +export FLOWEAVE_BACKEND="" + +detect_display_backend() { + local session_type="${XDG_SESSION_TYPE}" + + if [[ -z "${session_type}" ]] && command -v loginctl &> /dev/null; then + local session_id + session_id=$(loginctl --no-legend 2>/dev/null | awk -v u="$(whoami)" '$3 == u {print $1; exit}') + if [[ -n "${session_id}" ]]; then + session_type=$(loginctl show-session "${session_id}" -p Type --value 2>/dev/null) + fi + fi + + if [[ -z "${session_type}" ]]; then + if [[ -n "${WAYLAND_DISPLAY}" ]]; then + session_type="wayland" + elif [[ -n "${DISPLAY}" ]]; then + session_type="x11" + fi + fi + + case "${session_type}" in + x11) + FLOWEAVE_BACKEND="x11" + ;; + wayland) + local desktop="${XDG_CURRENT_DESKTOP:-${DESKTOP_SESSION:-}}" + if [[ "${desktop,,}" =~ gnome ]]; then + FLOWEAVE_BACKEND="gnome-wayland" + else + FLOWEAVE_BACKEND="unsupported" + fi + ;; + *) + FLOWEAVE_BACKEND="unsupported" + ;; + esac + + export FLOWEAVE_BACKEND + return 0 +} + +get_backend_name() { + case "${FLOWEAVE_BACKEND}" in + x11) + echo "Xorg (X11)" + ;; + gnome-wayland) + echo "GNOME on Wayland" + ;; + unsupported) + echo "Unsupported" + ;; + *) + echo "Unknown" + ;; + esac +} diff --git a/modules/display-manager.sh b/modules/display-manager.sh index 3107b93..b5b4fd3 100755 --- a/modules/display-manager.sh +++ b/modules/display-manager.sh @@ -1,34 +1,28 @@ #!/bin/bash -################################################################################ -# Floweave - Display Manager Module -# -# Functions: -# - get_primary_display() -# - create_virtual_display() -# - remove_virtual_display() -# - calculate_display_geometry() -################################################################################ - -# Guard against multiple sourcing + [[ -n "${FLOWEAVE_DISPLAY_MANAGER_LOADED}" ]] && return FLOWEAVE_DISPLAY_MANAGER_LOADED=1 -# Source dependencies FLOWEAVE_MODULE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$FLOWEAVE_MODULE_DIR/ui-helpers.sh" source "$FLOWEAVE_MODULE_DIR/config-manager.sh" +source "$FLOWEAVE_MODULE_DIR/display-backend.sh" +source "$FLOWEAVE_MODULE_DIR/wayland-display-manager.sh" -# get_primary_display() get_primary_display() { + detect_display_backend + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + get_primary_display_wayland + return $? + fi + local primary_display="" local primary_resolution="" local primary_width="" local primary_height="" - # Try to get primary display primary_display=$(xrandr 2>/dev/null | grep " connected primary" | cut -d' ' -f1) - # If no primary, get first connected display if [[ -z "$primary_display" ]]; then primary_display=$(xrandr 2>/dev/null | grep " connected" | head -1 | cut -d' ' -f1) fi @@ -38,7 +32,6 @@ get_primary_display() { return 1 fi - # Get resolution primary_resolution=$(xrandr 2>/dev/null | grep "$primary_display" | grep -o "[0-9]*x[0-9]*" | head -1) if [[ -z "$primary_resolution" ]]; then @@ -49,7 +42,6 @@ get_primary_display() { primary_width=$(echo "$primary_resolution" | cut -d'x' -f1) primary_height=$(echo "$primary_resolution" | cut -d'x' -f2) - # Export for use by other functions export PRIMARY_DISPLAY="$primary_display" export PRIMARY_WIDTH="$primary_width" export PRIMARY_HEIGHT="$primary_height" @@ -58,18 +50,20 @@ get_primary_display() { return 0 } -# calculate_display_geometry() calculate_display_geometry() { + detect_display_backend + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + return 0 + fi + local position="${CONFIG[display_position]}" local width="${CONFIG[display_width]}" local height="${CONFIG[display_height]}" - # Get primary display info if ! get_primary_display; then return 1 fi - # Calculate offset and xrandr position based on position case "$position" in "right") export OFFSET_X="$PRIMARY_WIDTH" @@ -102,41 +96,44 @@ calculate_display_geometry() { return 0 } -# create_virtual_display() create_virtual_display() { + detect_display_backend + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + create_virtual_display_wayland + return $? + fi + local width="${CONFIG[display_width]}" local height="${CONFIG[display_height]}" local position="${CONFIG[display_position]}" show_info "Creating virtual display: ${width}x${height} (${position})" - # Get primary display info if ! get_primary_display; then return 1 fi - # Calculate geometry if ! calculate_display_geometry; then return 1 fi - # Generate modeline using cvt - local modeline_output=$(cvt "$width" "$height" 60 2>/dev/null | grep "Modeline") + local modeline_output + modeline_output=$(cvt "$width" "$height" 60 2>/dev/null | grep "Modeline") if [[ -z "$modeline_output" ]]; then show_error "Failed to generate modeline for ${width}x${height}" return 1 fi - # Extract mode name and parameters - local mode_name=$(echo "$modeline_output" | cut -d' ' -f2 | tr -d '"') - local mode_params=$(echo "$modeline_output" | cut -d' ' -f3-) + local mode_name + mode_name=$(echo "$modeline_output" | cut -d' ' -f2 | tr -d '"') + local mode_params + mode_params=$(echo "$modeline_output" | cut -d' ' -f3-) - # Create new mode (ignore error if already exists) xrandr --newmode "$mode_name" $mode_params 2>/dev/null - # Get list of all disconnected outputs - local disconnected_outputs=$(xrandr 2>/dev/null | grep " disconnected" | cut -d' ' -f1) + local disconnected_outputs + disconnected_outputs=$(xrandr 2>/dev/null | grep " disconnected" | cut -d' ' -f1) if [[ -z "$disconnected_outputs" ]]; then show_error "No disconnected display output found" @@ -157,29 +154,21 @@ create_virtual_display() { fi done - # Combine lists (prioritized first) local target_outputs="$prioritized_outputs $other_outputs" - - # Iterate through outputs until one works local success=false local target_output="" for output in $target_outputs; do - # Skip empty strings [[ -z "$output" ]] && continue show_info "Trying output: $output..." - - # Add mode to output (ignore error if already added) xrandr --addmode "$output" "$mode_name" 2>/dev/null - # Try to enable if xrandr --output "$output" --mode "$mode_name" $XRANDR_POS "$PRIMARY_DISPLAY" 2>/dev/null; then target_output="$output" success=true break else - # If failed, remove mode from this output to clean up xrandr --delmode "$output" "$mode_name" 2>/dev/null fi done @@ -190,19 +179,22 @@ create_virtual_display() { return 1 fi - # Save display name for cleanup + mkdir -p "$(dirname "$FLOWEAVE_DISPLAY_FILE")" echo "$target_output" > "$FLOWEAVE_DISPLAY_FILE" show_success "Virtual display enabled on $target_output" - return 0 } -# remove_virtual_display() remove_virtual_display() { + detect_display_backend + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]] || { [[ -f "$FLOWEAVE_DISPLAY_FILE" ]] && grep -q "wayland-extend" "$FLOWEAVE_DISPLAY_FILE" 2>/dev/null; }; then + remove_virtual_display_wayland + return $? + fi + local display_name="" - # Try to get display name from file if [[ -f "$FLOWEAVE_DISPLAY_FILE" ]]; then display_name=$(cat "$FLOWEAVE_DISPLAY_FILE" 2>/dev/null) @@ -214,12 +206,11 @@ remove_virtual_display() { rm -f "$FLOWEAVE_DISPLAY_FILE" fi - # Fallback: try to find and disable any connected virtual displays - local virtual_displays=$(xrandr 2>/dev/null | grep -E "(HDMI|VGA|VIRTUAL|DP-[2-9])" | grep " connected" | cut -d' ' -f1) + local virtual_displays + virtual_displays=$(xrandr 2>/dev/null | grep -E "(HDMI|VGA|VIRTUAL|DP-[2-9])" | grep " connected" | cut -d' ' -f1) if [[ -n "$virtual_displays" ]]; then while IFS= read -r display; do - # Skip if it's the primary display if [[ "$display" != "$PRIMARY_DISPLAY" ]]; then show_info "Disabling display: $display" xrandr --output "$display" --off 2>/dev/null @@ -228,6 +219,5 @@ remove_virtual_display() { fi show_success "Virtual display removed" - return 0 } diff --git a/modules/system-checker.sh b/modules/system-checker.sh index c6ceb26..86bc7a1 100755 --- a/modules/system-checker.sh +++ b/modules/system-checker.sh @@ -1,84 +1,63 @@ #!/bin/bash -################################################################################ -# Floweave - System Checker Module -# -# Functions: -# - check_display_server() -# - get_display_info() -# - validate_network() -# - get_system_info() -# - check_permissions() -################################################################################ - -# Source UI helpers for message functions (if not already loaded) + if ! command -v show_info &> /dev/null; then SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${SCRIPT_DIR}/ui-helpers.sh" fi -# check_display_server() check_display_server() { show_info "Checking display server..." - # Method 1: Check XDG_SESSION_TYPE environment variable - if [[ -n "${XDG_SESSION_TYPE}" ]]; then - if [[ "${XDG_SESSION_TYPE}" == "x11" ]]; then + local module_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + source "$module_dir/display-backend.sh" + detect_display_backend + + case "$FLOWEAVE_BACKEND" in + x11) show_success "Display server: Xorg (X11) - Compatible βœ“" return 0 - elif [[ "${XDG_SESSION_TYPE}" == "wayland" ]]; then - show_error "Display server: Wayland - NOT COMPATIBLE βœ—" - show_warning "Floweave requires Xorg (X11). Please switch to an X11 session." - show_info "To switch: Log out, click the gear icon at login, and select 'X11' or 'Xorg' session" + ;; + gnome-wayland) + show_success "Display server: Wayland (GNOME) - Compatible βœ“" + return 0 + ;; + unsupported) + local desktop="${XDG_CURRENT_DESKTOP:-${DESKTOP_SESSION:-unknown}}" + show_error "Unsupported display configuration" + if [[ "${XDG_SESSION_TYPE}" == "wayland" || -n "${WAYLAND_DISPLAY}" ]]; then + show_warning "Wayland compositor '$desktop' is not supported." + show_info "Wayland support is currently limited to GNOME (Mutter)." + show_info "KDE Plasma, Hyprland, and other compositors are not supported." + show_info "Switch to a GNOME Wayland session or an Xorg (X11) session to use Floweave." + else + show_warning "Could not detect a compatible display server." + show_info "Floweave supports Xorg (X11) and GNOME Wayland." + fi return 1 - fi - fi + ;; + esac +} - # Method 2: Check WAYLAND_DISPLAY environment variable - if [[ -n "${WAYLAND_DISPLAY}" ]]; then - show_error "Display server: Wayland - NOT COMPATIBLE βœ—" - show_warning "Floweave requires Xorg (X11). Please switch to an X11 session." - return 1 - fi +get_display_info() { + show_info "Gathering display information..." - # Method 3: Check if DISPLAY is set and xrandr works (indicates X11) - if [[ -n "${DISPLAY}" ]]; then - if command -v xrandr &> /dev/null && xrandr &> /dev/null; then - show_success "Display server: Xorg (X11) - Compatible βœ“" - return 0 - fi - fi + local module_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + source "$module_dir/display-backend.sh" + detect_display_backend - # Method 4: Check loginctl session type - if command -v loginctl &> /dev/null; then - local session_type=$(loginctl show-session $(loginctl | grep $(whoami) | awk '{print $1}') -p Type --value 2>/dev/null) - if [[ "${session_type}" == "x11" ]]; then - show_success "Display server: Xorg (X11) - Compatible βœ“" + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + source "$module_dir/wayland-display-manager.sh" + if get_primary_display_wayland; then + echo "" + show_success "Primary display: ${PRIMARY_DISPLAY}" + show_info "Current mode: ${PRIMARY_RESOLUTION}" return 0 - elif [[ "${session_type}" == "wayland" ]]; then - show_error "Display server: Wayland - NOT COMPATIBLE βœ—" - show_warning "Floweave requires Xorg (X11). Please switch to an X11 session." + else + show_warning "No active display detected via Mutter" return 1 fi fi - # Fallback: Unable to determine display server - show_warning "Unable to determine display server type" - show_info "Attempting to verify X11 compatibility..." - - if command -v xrandr &> /dev/null && xrandr &> /dev/null; then - show_success "xrandr is working - Assuming Xorg (X11) βœ“" - return 0 - else - show_error "Cannot verify X11 compatibility" - show_warning "Floweave requires Xorg (X11) to function properly" - return 1 - fi -} - -# get_display_info() -get_display_info() { - show_info "Gathering display information..." - if ! command -v xrandr &> /dev/null; then show_error "xrandr is not installed" return 1 @@ -86,20 +65,19 @@ get_display_info() { echo "" - # Get primary display - local primary_display=$(xrandr | grep " connected primary" | awk '{print $1}') + local primary_display + primary_display=$(xrandr | grep " connected primary" | awk '{print $1}') if [[ -n "${primary_display}" ]]; then show_success "Primary display: ${primary_display}" - # Get current resolution and refresh rate - local current_mode=$(xrandr | grep "${primary_display}" -A 1 | grep "\*" | awk '{print $1, $2}') + local current_mode + current_mode=$(xrandr | grep "${primary_display}" -A 1 | grep "\*" | awk '{print $1, $2}') if [[ -n "${current_mode}" ]]; then show_info "Current mode: ${current_mode}" fi else show_warning "No primary display detected" - # Try to get first connected display primary_display=$(xrandr | grep " connected" | head -1 | awk '{print $1}') if [[ -n "${primary_display}" ]]; then show_info "First connected display: ${primary_display}" @@ -109,8 +87,10 @@ get_display_info() { echo "" show_info "Connected displays:" xrandr | grep " connected" | while read -r line; do - local display_name=$(echo "${line}" | awk '{print $1}') - local display_info=$(echo "${line}" | grep -o "[0-9]*x[0-9]*+[0-9]*+[0-9]*" | head -1) + local display_name + display_name=$(echo "${line}" | awk '{print $1}') + local display_info + display_info=$(echo "${line}" | grep -o "[0-9]*x[0-9]*+[0-9]*+[0-9]*" | head -1) if [[ -n "${display_info}" ]]; then echo " ${ARROW_RIGHT} ${display_name}: ${line#*connected }" else @@ -119,18 +99,15 @@ get_display_info() { done echo "" - return 0 } -# validate_network() validate_network() { show_info "Validating network connectivity..." - echo "" - # Check if any network interface is up - local active_interfaces=$(ip link show | grep "state UP" | awk -F: '{print $2}' | tr -d ' ') + local active_interfaces + active_interfaces=$(ip link show | grep "state UP" | awk -F: '{print $2}' | tr -d ' ') if [[ -z "${active_interfaces}" ]]; then show_error "No active network interfaces found" @@ -140,9 +117,9 @@ validate_network() { show_success "Active network interfaces:" - # Get IP addresses for each active interface while IFS= read -r interface; do - local ip_addr=$(ip addr show "${interface}" | grep "inet " | awk '{print $2}' | cut -d'/' -f1) + local ip_addr + ip_addr=$(ip addr show "${interface}" | grep "inet " | awk '{print $2}' | cut -d'/' -f1) if [[ -n "${ip_addr}" ]]; then echo " ${ARROW_RIGHT} ${interface}: ${ip_addr}" fi @@ -150,7 +127,6 @@ validate_network() { echo "" - # Test local network stack if ping -c 1 -W 1 127.0.0.1 &> /dev/null; then show_success "Local network stack: Working βœ“" else @@ -159,77 +135,80 @@ validate_network() { echo "" show_info "Network validation complete" - return 0 } -# get_system_info() get_system_info() { show_info "Gathering system information..." - echo "" - # OS Information if [[ -f /etc/os-release ]]; then source /etc/os-release show_info "Operating System: ${NAME} ${VERSION_ID} (${VERSION_CODENAME:-N/A})" fi - # Kernel version - local kernel=$(uname -r) + local kernel + kernel=$(uname -r) show_info "Kernel: ${kernel}" - # Architecture - local arch=$(uname -m) + local arch + arch=$(uname -m) show_info "Architecture: ${arch}" - # Desktop Environment if [[ -n "${XDG_CURRENT_DESKTOP}" ]]; then show_info "Desktop Environment: ${XDG_CURRENT_DESKTOP}" fi - # Display Server if [[ -n "${XDG_SESSION_TYPE}" ]]; then show_info "Session Type: ${XDG_SESSION_TYPE}" fi - # Hostname - local hostname=$(hostname) + local hostname + hostname=$(hostname) show_info "Hostname: ${hostname}" - # Current user - local current_user=$(whoami) + local current_user + current_user=$(whoami) show_info "User: ${current_user}" - # System uptime if command -v uptime &> /dev/null; then - local uptime_info=$(uptime -p 2>/dev/null || uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1}') + local uptime_info + uptime_info=$(uptime -p 2>/dev/null || uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1}') show_info "Uptime: ${uptime_info}" fi echo "" - return 0 } -# check_permissions() check_permissions() { show_info "Checking user permissions..." - echo "" local permission_issues=0 - # Check X11 display access - if command -v xrandr &> /dev/null && xrandr &> /dev/null; then - show_success "X11 display access: OK βœ“" + local module_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + source "$module_dir/display-backend.sh" + detect_display_backend + + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + if gdbus call --session --dest org.gnome.Mutter.DisplayConfig --object-path /org/gnome/Mutter/DisplayConfig --method org.gnome.Mutter.DisplayConfig.GetCurrentState &> /dev/null; then + show_success "Wayland session display access: OK βœ“" + else + show_error "Wayland session display access: DENIED βœ—" + show_warning "Cannot query Mutter DisplayConfig via D-Bus." + permission_issues=$((permission_issues + 1)) + fi else - show_error "X11 display access: DENIED βœ—" - show_warning "Cannot access X11 display. Check DISPLAY variable and xhost permissions." - permission_issues=$((permission_issues + 1)) + if command -v xrandr &> /dev/null && xrandr &> /dev/null; then + show_success "X11 display access: OK βœ“" + else + show_error "X11 display access: DENIED βœ—" + show_warning "Cannot access X11 display. Check DISPLAY variable and xhost permissions." + permission_issues=$((permission_issues + 1)) + fi fi - # Check home directory write access if [[ -w "${HOME}" ]]; then show_success "Home directory write access: OK βœ“" else diff --git a/modules/ui-helpers.sh b/modules/ui-helpers.sh index 5f8c7b3..a64fa0e 100755 --- a/modules/ui-helpers.sh +++ b/modules/ui-helpers.sh @@ -1,28 +1,10 @@ #!/bin/bash -################################################################################ -# Floweave - UI Helpers Module -# -# Functions: -# - show_header() -# - show_menu() -# - prompt_input() -# - prompt_yes_no() -# - prompt_with_default() -# - show_success() -# - show_error() -# - show_warning() -# - show_info() -# - show_separator() -# - show_box() -# - press_any_key() -# - show_loading() -################################################################################ -# Color Codes and Formatting +[[ -n "${FLOWEAVE_UI_HELPERS_LOADED}" ]] && return 0 +FLOWEAVE_UI_HELPERS_LOADED=1 -# Check if terminal supports colors +# Color Codes and Formatting if [[ -t 1 ]] && command -v tput &> /dev/null && tput setaf 1 &> /dev/null; then - # Color codes RED="\033[0;31m" GREEN="\033[0;32m" YELLOW="\033[1;33m" @@ -33,7 +15,6 @@ if [[ -t 1 ]] && command -v tput &> /dev/null && tput setaf 1 &> /dev/null; then DIM="\033[2m" RESET="\033[0m" else - # No color support RED="" GREEN="" YELLOW="" @@ -58,9 +39,8 @@ else ARROW_RIGHT="->" fi -# show_header() show_header() { - clear + clear 2>/dev/null || true echo -e "${DIM}β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”${RESET}" @@ -98,12 +78,12 @@ show_header() { local info_right=$(( box_width - info_len - info_left )) printf "${DIM}β”‚${RESET}%*s${GREEN}${BOLD}%s${RESET}%*s${DIM}β”‚${RESET}\n" $info_left "" "$info_line" $info_right "" - # Center-aligned Xorg warning in YELLOW (Inside box) - local warning="${WARNING_SIGN} Requires Xorg (X11) - Not compatible with Wayland" - local warning_len=${#warning} - local warn_left=$(( (box_width - warning_len) / 2 )) - local warn_right=$(( box_width - warning_len - warn_left )) - printf "${DIM}β”‚${RESET}%*s${YELLOW}%s${RESET}%*s${DIM}β”‚${RESET}\n" $warn_left "" "$warning" $warn_right "" + # Center-aligned supported session info in CYAN (Inside box) + local mode_info="Supports Xorg (X11) and GNOME Wayland" + local mode_len=${#mode_info} + local mode_left=$(( (box_width - mode_len) / 2 )) + local mode_right=$(( box_width - mode_len - mode_left )) + printf "${DIM}β”‚${RESET}%*s${CYAN}%s${RESET}%*s${DIM}β”‚${RESET}\n" $mode_left "" "$mode_info" $mode_right "" # Empty line echo -e "${DIM}β”‚${RESET} ${DIM}β”‚${RESET}" @@ -147,9 +127,7 @@ show_header() { } -# show_menu() show_menu() { - # Display header show_box "Available Options:" local options=( @@ -160,7 +138,6 @@ show_menu() { "Exit" ) - # Display menu options local i=1 for option in "${options[@]}"; do echo -e " ${CYAN}${BOLD}${i}.${RESET} ${option}" @@ -170,7 +147,6 @@ show_menu() { echo "" } -# prompt_input() prompt_input() { local prompt_msg="$1" local validation_regex="$2" @@ -180,7 +156,6 @@ prompt_input() { echo -ne "${BLUE}${ARROW_RIGHT}${RESET} ${prompt_msg}: " read -r user_input - # If no validation regex provided, accept any non-empty input if [[ -z "$validation_regex" ]]; then if [[ -n "$user_input" ]]; then echo "$user_input" @@ -189,7 +164,6 @@ prompt_input() { show_error "Input cannot be empty. Please try again." fi else - # Validate against regex if [[ "$user_input" =~ $validation_regex ]]; then echo "$user_input" return 0 @@ -200,13 +174,11 @@ prompt_input() { done } -# prompt_yes_no() prompt_yes_no() { local prompt_msg="$1" local default="${2:-}" local user_input - # Build prompt with default indicator local prompt_suffix if [[ "$default" == "y" ]]; then prompt_suffix="[Y/n]" @@ -220,7 +192,6 @@ prompt_yes_no() { echo -ne " ${CYAN}${BOLD}${ARROW_RIGHT}${RESET} ${prompt_msg} ${prompt_suffix}: " read -r user_input - # Use default if input is empty if [[ -z "$user_input" ]] && [[ -n "$default" ]]; then user_input="$default" fi @@ -240,7 +211,6 @@ prompt_yes_no() { done } -# prompt_with_default() prompt_with_default() { local prompt_msg="$1" local default_value="$2" @@ -249,7 +219,6 @@ prompt_with_default() { echo -ne "${BLUE}${ARROW_RIGHT}${RESET} ${prompt_msg} ${DIM}[default: ${default_value}]${RESET}: " read -r user_input - # Return default if input is empty if [[ -z "$user_input" ]]; then echo "$default_value" else @@ -257,50 +226,38 @@ prompt_with_default() { fi } -# show_success() show_success() { local message="$1" echo -e " ${GREEN}${CHECK_MARK} ${message}${RESET}" } -# show_error() show_error() { local message="$1" echo -e " ${RED}${CROSS_MARK} ${message}${RESET}" >&2 } -# show_warning() show_warning() { local message="$1" echo -e " ${YELLOW}${WARNING_SIGN} ${message}${RESET}" } -# show_info() show_info() { local message="$1" echo -e " ${BLUE}${BOLD}${message}${RESET}" } -# show_separator() show_separator() { echo -e "${DIM}────────────────────────────────────────────────────────────────────────────────${RESET}" } -# show_box() show_box() { local message="$1" - # Top border (80 characters wide) echo -e "${DIM}────────────────────────────────────────────────────────────────────────────────${RESET}" - - # Message echo -e " ${CYAN}${BOLD}${message}${RESET}" - - # Bottom border (80 characters wide) echo -e "${DIM}────────────────────────────────────────────────────────────────────────────────${RESET}" } -# press_any_key() press_any_key() { echo "" echo -ne " ${DIM}Press any key to continue...${RESET}" @@ -308,7 +265,6 @@ press_any_key() { echo "" } -# show_loading() show_loading() { local message="$1" local duration="${2:-3}" diff --git a/modules/vnc-server.sh b/modules/vnc-server.sh index ae47146..28c6662 100755 --- a/modules/vnc-server.sh +++ b/modules/vnc-server.sh @@ -1,36 +1,89 @@ #!/bin/bash -################################################################################ -# Floweave - VNC Server Module -# -# Functions: -# - start_vnc_server() -# - stop_vnc_server() -# - get_vnc_status() -################################################################################ - -# Guard against multiple sourcing + [[ -n "${FLOWEAVE_VNC_SERVER_LOADED}" ]] && return FLOWEAVE_VNC_SERVER_LOADED=1 -# Source dependencies FLOWEAVE_MODULE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$FLOWEAVE_MODULE_DIR/ui-helpers.sh" source "$FLOWEAVE_MODULE_DIR/config-manager.sh" source "$FLOWEAVE_MODULE_DIR/display-manager.sh" -# start_vnc_server() +start_vnc_server_wayland() { + local port="${CONFIG[vnc_port]:-5900}" + local password="${CONFIG[vnc_password]}" + + show_info "Starting GNOME Remote Desktop VNC on port $port..." + + grdctl vnc set-port "$port" 2>/dev/null + grdctl vnc disable-view-only 2>/dev/null + + if [[ -n "$password" ]]; then + grdctl vnc set-auth-method password 2>/dev/null + grdctl vnc set-password "$password" 2>/dev/null + else + grdctl vnc clear-password 2>/dev/null + grdctl vnc set-auth-method prompt 2>/dev/null + fi + + grdctl vnc enable 2>/dev/null + + if ! systemctl --user restart gnome-remote-desktop.service 2>/dev/null; then + show_error "Failed to start gnome-remote-desktop service" + return 1 + fi + + sleep 1 + + if ! grdctl status 2>/dev/null | grep -A 3 "VNC:" | grep -q "Status: enabled"; then + show_error "Failed to activate VNC backend in GNOME Remote Desktop" + return 1 + fi + + local pid + pid=$(systemctl --user show --property MainPID --value gnome-remote-desktop.service 2>/dev/null) + if [[ -z "$pid" || "$pid" == "0" ]]; then + pid=$(pgrep -u "$USER" -f gnome-remote-desktop-daemon | head -1) + fi + + if [[ -n "$pid" && "$pid" =~ ^[0-9]+$ && "$pid" -gt 0 ]]; then + mkdir -p "$(dirname "$FLOWEAVE_PID_FILE")" + echo "$pid" > "$FLOWEAVE_PID_FILE" + fi + + local ip_addr + ip_addr=$(hostname -I 2>/dev/null | awk '{print $1}') + [[ -z "$ip_addr" ]] && ip_addr="" + + show_success "VNC server started (gnome-remote-desktop)" + show_info "Connection: ${ip_addr}:${port}" + + return 0 +} + +stop_vnc_server_wayland() { + grdctl vnc disable 2>/dev/null + systemctl --user restart gnome-remote-desktop.service 2>/dev/null + rm -f "$FLOWEAVE_PID_FILE" + show_success "VNC server stopped" + return 0 +} + start_vnc_server() { local port="${CONFIG[vnc_port]}" local password="${CONFIG[vnc_password]}" - # Check if already running if is_running; then show_error "VNC server is already running" show_info "Use 'floweave stop' to stop it first" return 1 fi - # Calculate display geometry + detect_display_backend + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then + start_vnc_server_wayland + return $? + fi + if ! calculate_display_geometry; then return 1 fi @@ -38,7 +91,6 @@ start_vnc_server() { show_info "Starting VNC server on port $port" show_info "Clip region: $CLIP_GEOMETRY" - # Build x11vnc command (cursor flags match original linux-display-extend project) local vnc_cmd="x11vnc -display :0" vnc_cmd="$vnc_cmd -clip $CLIP_GEOMETRY" vnc_cmd="$vnc_cmd -rfbport $port" @@ -53,57 +105,44 @@ start_vnc_server() { vnc_cmd="$vnc_cmd -buttonmap 123" vnc_cmd="$vnc_cmd -fixscreen V=3.0" vnc_cmd="$vnc_cmd -desktop Floweave-$USER" - # Latency optimizations - vnc_cmd="$vnc_cmd -wait 5" + vnc_cmd="$vnc_cmd -wait 5" vnc_cmd="$vnc_cmd -defer 5" - # Add password if configured if [[ -n "$password" ]]; then vnc_cmd="$vnc_cmd -passwd $password" else vnc_cmd="$vnc_cmd -nopw" fi - # CRITICAL FIX: Start VNC server in a subshell with signal isolation - # This prevents SIGINT (Ctrl+C) from propagating to the VNC process + # Start in an isolated session so Ctrl+C does not terminate the background daemon ( - # Create a new process group and session setsid bash -c " - # Ignore SIGINT and SIGTERM in this subshell trap '' SIGINT SIGTERM - - # Start VNC server with nohup (ignores SIGHUP) nohup $vnc_cmd >/dev/null 2>&1 & - - # Get the PID and save it + mkdir -p '$(dirname "$FLOWEAVE_PID_FILE")' echo \$! > '$FLOWEAVE_PID_FILE' " >/dev/null 2>&1 & ) - # Wait for VNC process to fully detach and start sleep 2 - # Read the saved PID if [[ ! -f "$FLOWEAVE_PID_FILE" ]]; then show_error "Failed to create PID file" return 1 fi - local vnc_pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) + local vnc_pid + vnc_pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) - # Verify VNC server started if [[ -z "$vnc_pid" ]] || ! ps -p "$vnc_pid" > /dev/null 2>&1; then show_error "VNC server failed to start" rm -f "$FLOWEAVE_PID_FILE" return 1 fi - # Get IP address for connection info - local ip_addr=$(hostname -I 2>/dev/null | awk '{print $1}') - - if [[ -z "$ip_addr" ]]; then - ip_addr="" - fi + local ip_addr + ip_addr=$(hostname -I 2>/dev/null | awk '{print $1}') + [[ -z "$ip_addr" ]] && ip_addr="" show_success "VNC server started (PID: $vnc_pid)" show_info "Connection: ${ip_addr}:${port}" @@ -111,28 +150,30 @@ start_vnc_server() { return 0 } -# stop_vnc_server() stop_vnc_server() { - # show_info "Stopping VNC server" + detect_display_backend - # Check if PID file exists - if [[ -f "$FLOWEAVE_PID_FILE" ]]; then - local pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) + local pid="" + [[ -f "$FLOWEAVE_PID_FILE" ]] && pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) + local comm="" + [[ -n "$pid" && "$pid" =~ ^[0-9]+$ ]] && comm=$(ps -p "$pid" -o comm= 2>/dev/null) + if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" || "$comm" =~ gnome-remote ]]; then + stop_vnc_server_wayland + return $? + fi + + if [[ -f "$FLOWEAVE_PID_FILE" ]]; then if [[ -n "$pid" && "$pid" =~ ^[0-9]+$ ]]; then - # Check if process is running if ps -p "$pid" > /dev/null 2>&1; then - # Kill the process kill "$pid" 2>/dev/null - # Wait for process to terminate local count=0 while ps -p "$pid" > /dev/null 2>&1 && [[ $count -lt 5 ]]; do sleep 1 count=$((count + 1)) done - # Force kill if still running if ps -p "$pid" > /dev/null 2>&1; then kill -9 "$pid" 2>/dev/null fi @@ -141,35 +182,31 @@ stop_vnc_server() { fi fi - # Remove PID file rm -f "$FLOWEAVE_PID_FILE" fi - # Fallback: kill any x11vnc processes with "Floweave" in desktop name pkill -f "x11vnc.*Floweave" 2>/dev/null return 0 } -# get_vnc_status() get_vnc_status() { if is_running; then - local pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) + local pid + pid=$(cat "$FLOWEAVE_PID_FILE" 2>/dev/null) local port="${CONFIG[vnc_port]}" - local ip_addr=$(hostname -I 2>/dev/null | awk '{print $1}') - - if [[ -z "$ip_addr" ]]; then - ip_addr="" - fi + local ip_addr + ip_addr=$(hostname -I 2>/dev/null | awk '{print $1}') + [[ -z "$ip_addr" ]] && ip_addr="" - echo "Status: ${COLOR_GREEN}RUNNING${COLOR_RESET}" + echo -e "Status: ${GREEN}RUNNING${RESET}" echo "PID: $pid" echo "Port: $port" - echo "Connection: ${COLOR_CYAN}${ip_addr}:${port}${COLOR_RESET}" + echo -e "Connection: ${CYAN}${ip_addr}:${port}${RESET}" return 0 else - echo "Status: ${COLOR_RED}STOPPED${COLOR_RESET}" + echo -e "Status: ${RED}STOPPED${RESET}" return 1 fi } diff --git a/modules/wayland-display-manager.sh b/modules/wayland-display-manager.sh new file mode 100644 index 0000000..c4b7271 --- /dev/null +++ b/modules/wayland-display-manager.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +[[ -n "${FLOWEAVE_WAYLAND_DISPLAY_MANAGER_LOADED}" ]] && return +FLOWEAVE_WAYLAND_DISPLAY_MANAGER_LOADED=1 + +FLOWEAVE_MODULE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$FLOWEAVE_MODULE_DIR/ui-helpers.sh" +source "$FLOWEAVE_MODULE_DIR/config-manager.sh" + +get_primary_display_wayland() { + local primary_display="" + local primary_resolution="" + local primary_width="" + local primary_height="" + + local dbus_output + dbus_output=$(gdbus call --session \ + --dest org.gnome.Mutter.DisplayConfig \ + --object-path /org/gnome/Mutter/DisplayConfig \ + --method org.gnome.Mutter.DisplayConfig.GetCurrentState 2>/dev/null) + + if [[ -z "$dbus_output" ]]; then + show_error "No connected display found (gdbus call failed)" + return 1 + fi + + primary_display=$(echo "$dbus_output" | grep -oP '\(\(\x27\K[^\x27]+' | head -1) + + if [[ -z "$primary_display" ]]; then + show_error "No connected display found" + return 1 + fi + + primary_resolution=$(echo "$dbus_output" \ + | grep -oP '\d+, \d+,.*?is-current' \ + | head -1 \ + | grep -oP '^\d+, \d+' \ + | head -1) + + if [[ -z "$primary_resolution" ]]; then + primary_resolution=$(echo "$dbus_output" | grep -oP "\x27[0-9]+x[0-9]+(?=@[^\x27]*\x27[^\)]*is-current)" | tr -d "'" | head -1) + if [[ -n "$primary_resolution" ]]; then + primary_width=$(echo "$primary_resolution" | cut -d'x' -f1) + primary_height=$(echo "$primary_resolution" | cut -d'x' -f2) + fi + else + primary_width=$(echo "$primary_resolution" | cut -d',' -f1 | tr -d ' ') + primary_height=$(echo "$primary_resolution" | cut -d',' -f2 | tr -d ' ') + fi + + if [[ -z "$primary_width" || -z "$primary_height" ]]; then + show_error "Could not determine resolution for $primary_display" + return 1 + fi + + export PRIMARY_DISPLAY="$primary_display" + export PRIMARY_WIDTH="$primary_width" + export PRIMARY_HEIGHT="$primary_height" + export PRIMARY_RESOLUTION="${primary_width}x${primary_height}" + + return 0 +} + +create_virtual_display_wayland() { + local width="${CONFIG[display_width]}" + local height="${CONFIG[display_height]}" + local position="${CONFIG[display_position]}" + + show_info "Creating virtual display: ${width}x${height} (${position})" + + if ! get_primary_display_wayland; then + return 1 + fi + + # Extend mode prompts Mutter to create a virtual monitor when a client connects + if ! gsettings set org.gnome.desktop.remote-desktop.vnc screen-share-mode 'extend' 2>/dev/null; then + show_error "Failed to set VNC screen-share-mode to extend" + return 1 + fi + + mkdir -p "$(dirname "$FLOWEAVE_DISPLAY_FILE")" + echo "wayland-extend" > "$FLOWEAVE_DISPLAY_FILE" + + show_success "Virtual display enabled (Wayland extend mode)" + return 0 +} + +remove_virtual_display_wayland() { + show_info "Removing virtual display (Wayland)" + + gsettings set org.gnome.desktop.remote-desktop.vnc screen-share-mode 'mirror-primary' 2>/dev/null + rm -f "$FLOWEAVE_DISPLAY_FILE" + + show_success "Virtual display removed" + return 0 +} From 1beba7ba654206167b17175656e3937a79af5337 Mon Sep 17 00:00:00 2001 From: Prashant Adhikari Date: Mon, 7 Sep 2026 15:27:41 +0545 Subject: [PATCH 2/2] fix: address review feedback on Wayland backend and config --- modules/config-manager.sh | 6 +++++- modules/dependency-installer.sh | 2 -- modules/vnc-server.sh | 10 +++++++++- modules/wayland-display-manager.sh | 7 ++----- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/modules/config-manager.sh b/modules/config-manager.sh index 5b29c1e..13f121c 100755 --- a/modules/config-manager.sh +++ b/modules/config-manager.sh @@ -208,7 +208,11 @@ EOF CONFIG[display_monitor]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "display" "monitor" "") CONFIG[vnc_port]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "vnc" "port" "5900") CONFIG[vnc_password]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "vnc" "password" "") - CONFIG[system_version]="${FLOWEAVE_VERSION:-$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "system" "version" "1.0.0")}" + if [[ -n "${FLOWEAVE_VERSION}" && "${FLOWEAVE_VERSION}" != "unknown" ]]; then + CONFIG[system_version]="${FLOWEAVE_VERSION}" + else + CONFIG[system_version]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "system" "version" "1.0.0") + fi CONFIG[system_last_updated]=$(read_ini_value "$FLOWEAVE_CONFIG_FILE" "system" "last_updated" "") return 0 diff --git a/modules/dependency-installer.sh b/modules/dependency-installer.sh index e9a2ef4..90493c8 100755 --- a/modules/dependency-installer.sh +++ b/modules/dependency-installer.sh @@ -63,8 +63,6 @@ check_dependencies_silent() { if [[ "$FLOWEAVE_BACKEND" == "gnome-wayland" ]]; then all_deps=( "grdctl:gnome-remote-desktop" - "gdbus:glib" - "gsettings:glib" ) else all_deps=( diff --git a/modules/vnc-server.sh b/modules/vnc-server.sh index 28c6662..6e7b2ab 100755 --- a/modules/vnc-server.sh +++ b/modules/vnc-server.sh @@ -9,6 +9,11 @@ source "$FLOWEAVE_MODULE_DIR/config-manager.sh" source "$FLOWEAVE_MODULE_DIR/display-manager.sh" start_vnc_server_wayland() { + if ! command -v grdctl &> /dev/null; then + show_error "grdctl is not installed (gnome-remote-desktop required)" + return 1 + fi + local port="${CONFIG[vnc_port]:-5900}" local password="${CONFIG[vnc_password]}" @@ -62,7 +67,10 @@ start_vnc_server_wayland() { stop_vnc_server_wayland() { grdctl vnc disable 2>/dev/null - systemctl --user restart gnome-remote-desktop.service 2>/dev/null + if ! systemctl --user restart gnome-remote-desktop.service 2>/dev/null; then + show_error "Failed to restart gnome-remote-desktop service" + return 1 + fi rm -f "$FLOWEAVE_PID_FILE" show_success "VNC server stopped" return 0 diff --git a/modules/wayland-display-manager.sh b/modules/wayland-display-manager.sh index c4b7271..3ab8f80 100644 --- a/modules/wayland-display-manager.sh +++ b/modules/wayland-display-manager.sh @@ -62,11 +62,7 @@ get_primary_display_wayland() { } create_virtual_display_wayland() { - local width="${CONFIG[display_width]}" - local height="${CONFIG[display_height]}" - local position="${CONFIG[display_position]}" - - show_info "Creating virtual display: ${width}x${height} (${position})" + show_info "Enabling virtual display extension (GNOME Wayland)..." if ! get_primary_display_wayland; then return 1 @@ -82,6 +78,7 @@ create_virtual_display_wayland() { echo "wayland-extend" > "$FLOWEAVE_DISPLAY_FILE" show_success "Virtual display enabled (Wayland extend mode)" + show_info "Note: Display resolution and arrangement can be adjusted in GNOME Settings > Displays" return 0 }