#!/usr/bin/perl

use strict;
use warnings;
#use SimpleGtk2;
use lib `fvwm-perllib dir`;
use FVWM::Module::SimpleGtk2;
use Getopt::Long qw(:config no_ignore_case require_order pass_through);;

#-----------------------------------------------------------------------
# File:         FNS-CompConfigurator
my $Version =   '2.0.5';
# Licence:      GPL 2
#
# Description:  Composite configurator Perl script for xcompmgr or compton
#
# Author:       Thomas Funk <t.funk@web.de>    
#
# Created:      10/11/2014
# Changed:      02/16/2015
#-----------------------------------------------------------------------

my $module = new FVWM::Module::SimpleGtk2(
);

########################################################################
# Global values
########################################################################
SimpleGtk2::use_gettext("fns-comp-configurator", "$ENV{FVWM_USERDIR}/locale:$ENV{FNS_SYSTEMDIR}/locale:+");

# FNS systemdir
my $FNS_SYSTEMDIR = "$ENV{FNS_SYSTEMDIR}";

# FNS userdir
my $FVWM_USERDIR = "$ENV{FVWM_USERDIR}";

# used config path
my $config_path = "$FVWM_USERDIR/.settings";

my $compmgr = "none";
my $xcompmgr = `which xcompmgr  2> /dev/null |xargs basename  2> /dev/null`;
chomp($xcompmgr);
my $compton = `which compton  2> /dev/null |xargs basename  2> /dev/null`;
chomp($compton);
my $xcompActive = 1;

# default parameters
my $useCompositor = 0;
my $wanted_Comp = "";
my $stopCompmgr = "";
my $runButtonTitle = "Start";
my $cfg_changed; # will set later after gui initialize
my $execString = "";

my $enableShadows = 0;
my $noDockPanels = 1;
my $whileDnD = 0;
my $ShadowOpacity = 0.1;
my $BlurRadius = 12;
my $LeftOffset = -15;
my $TopOffset = -15;
my $ShadowColor = "";
my $ShadowColorSet = 0;
my $ShadowColorR = 0.0;
my $ShadowColorG = 0.0;
my $ShadowColorB = 0.0;

my $enableFading = 0;
my $onOpacityChanged = 0;
my $onOpenClose = 0;
my $FadeInSteps = 0.028;
my $FadeOutSteps = 0.03;
my $FadeStepTime = 10;

my $OpacityOnMenus = 1.0;
my $AdditionalParams = "";


########################################################################
# Common functions not depending on the GUI
########################################################################

#-----------------------------------------------------------------------
# Check if a comp manager is running
# returns 0 if not or 1
#-----------------------------------------------------------------------
sub CompOnTheRun {
    my $rc = 0;
    if ($compmgr ne "none") {
        if (`pidof xcompmgr` ne "") {
            $stopCompmgr = 'xcompmgr';
        }
        elsif (`pidof compton` ne "") {
            $stopCompmgr = 'compton';
        } else {
            $stopCompmgr = "";
        }
        if ($stopCompmgr ne "") {
            $runButtonTitle = "Stop";
            $rc = 1;
        } else {
            $runButtonTitle = "Start";
        }
    }
    return $rc;
}


########################################################################
# Main
########################################################################

# Parse command line arguments
my $numArgs = $#ARGV + 1;
# arguments found
if ($numArgs > 0) {
    my $i = 0;
    while($i < 1) {
        # the first and second argument could be enable (0|1)
        # or the wanted compositor
        if ($ARGV[$i] =~ /(0|1)/) {
            $useCompositor = shift (@ARGV);
        }
        elsif ($ARGV[$i] =~ /^compton/) {
            $xcompActive = 0;
            shift (@ARGV);
        }
        elsif ($ARGV[$i] =~ /^xcompmgr/) {
            $xcompActive = 1;
            shift (@ARGV);
        }
        else {$i++;}
    }

    # now parse the rest
    GetOptions(
                "C"     => sub{$noDockPanels = !$noDockPanels;},
                "c"     => \$enableShadows,
                "o=f"   => \$ShadowOpacity,
                "r=f"   => \$BlurRadius,
                "l=f"   => \$LeftOffset,
                "t=f"   => \$TopOffset,
                "f"     => \$enableFading,
                "F"     => \$onOpacityChanged,
                "I=f"   => \$FadeInSteps,
                "O=f"   => \$FadeOutSteps,
                "D=f"   => \$FadeStepTime,
                "G"     => \$whileDnD,
                "shadow-red=f"   => \$ShadowColorR,
                "shadow-green=f" => \$ShadowColorG,
                "shadow-blue=f"  => \$ShadowColorB,
                "no-fading-openclose" => \$onOpenClose,
                "m=f"   => \$OpacityOnMenus,
                );
    # put the rest in additional_parameters
    foreach (@ARGV) {
        $AdditionalParams = "$AdditionalParams $_";
    }
    $AdditionalParams =~ s/^ //;
}

# Set shadow RGB value from float
# hint: the $rounded is needed to round correct
my $rounded = sprintf("%.0f",($ShadowColorR*255));
my $hex = sprintf("%02X", $rounded);
$ShadowColor = $ShadowColor . $hex;
$rounded = sprintf("%.0f",($ShadowColorG*255));
$hex = sprintf("%02X", $rounded);
$ShadowColor = $ShadowColor . $hex;
$rounded = sprintf("%.0f",($ShadowColorB*255));
$hex = sprintf("%02X", $rounded);
$ShadowColor = $ShadowColor . $hex;

# Check if one or both composite managers are installed and set the respective variables
# check if xcompmgr is installed
if ($xcompmgr ne "") { $compmgr = $xcompmgr;}
# check if compton is installed
if ($compton ne "") {$compmgr ne "none" ? $compmgr = $compton : $compmgr = "both";}
# set $useCompositor to 0 if no composite manager is installed
if ($compmgr eq "none") {$useCompositor = 0;}

# Check if a comp manager is running
&CompOnTheRun();


########################################################################
# Graphical User Interface + corresponding functions
########################################################################

#-----------------------------------------------------------------------
# Toplevel window
#-----------------------------------------------------------------------
my $win = SimpleGtk2->new_window(  Name => 'mainWindow', 
                        Version => $Version,
                        Size => [470, 440], 
                        Title => "FNS Composite Configurator");
$win->add_signal_handler('mainWindow', 'delete_event', \&check_before_quit);


#-----------------------------------------------------------------------
# Composite Manager
#-----------------------------------------------------------------------
$win->add_frame( Name => 'CompFrame', 
        Pos     => [10, 10], 
        Size    => [450, 50], 
        Title   => " Composite Manager ");


# Use Comp -------------------------------------------------------------
$win->add_check_button( Name => 'checkUse', 
        Pos     => [10, 10], 
        Title   => 'Use', 
        Active  => $useCompositor, 
        Tip     => "Activate / deactivate the choosen composite manager.", 
        Frame   => 'CompFrame');
$win->add_signal_handler('checkUse', 'clicked', \&check_use_on, $win);

sub check_use_on {
    # get current state
    my $check_button_state = $win->is_active('checkUse');
    if ($check_button_state != $useCompositor) {
        &config_changed();
        # set sensitivity of the radio buttons if the respective
        # composite manager is installed.
        unless ($compmgr eq "none") {
            $useCompositor = $check_button_state;
            # if use of compositor want be deactivated do the same with the run button
            # but show a warning whether compositor is running
            if ($runButtonTitle eq 'Stop' and $check_button_state == 0) {
                my $response = $win->show_msg_dialog('warning', 'yes-no', "Composite manager is running! Stopping?");
                if ($response eq 'yes') {
                    &stopComp();
                    &config_changed();
                } else {
                    $win->set_value('checkUse', Active => 1);
                    $useCompositor = 1;
                }
            }
            $win->set_sensitive('radioXcompmgr', $useCompositor) if $xcompmgr ne "";
            $win->set_sensitive('radioCompton', $useCompositor) if $compton ne "";
            $win->set_sensitive('runButton', $useCompositor);
        }
    }
}


# XcompMgr -------------------------------------------------------------
$win->add_radio_button( Name => 'radioXcompmgr', 
        Pos     => [180, 10], 
        Title   => "XcompMgr", 
        Group   => "CompGroup", 
        Sens    => $useCompositor, 
        Tip     => "XcompMgr is the standard composition manager for the X Composite extension. \
                    It implements shadows, fading, proper translucency, and more.", 
        Frame   => 'CompFrame');
$win->add_signal_handler('radioXcompmgr', 'toggled', sub {&check_comp_on();});


# Compton --------------------------------------------------------------
$win->add_radio_button( Name => 'radioCompton', 
        Pos     => [330, 10], 
        Title   => "Compton", 
        Group   => "CompGroup", 
        Sens    => $useCompositor, 
        Tip     => "Compton is a compositor based on xcompmgr. In addition to shadows, \
                    fading and translucency, it implements window frame opacity control, inactive \
                    window transparency, and shadows on argb windows.", 
        Frame   => 'CompFrame');

sub check_comp_on {
    if ($win->is_active('radioXcompmgr')) {
        $win->set_value('radioXcompmgr', 'Active' => 1);
        &set_xcompmgr_widgets();
    } else {
        $win->set_value('radioCompton', 'Active' => 1);
        &set_compton_widgets();
    }
    &config_changed();
}


#-----------------------------------------------------------------------
# Shadows
#-----------------------------------------------------------------------
$win->add_frame( Name => 'ShadowsFrame', 
        Pos     => [10, 70], 
        Size    => [220, 250], 
        Title   => " Shadows ");


# Enable Shadows -------------------------------------------------------
$win->add_check_button( Name => 'checkShadowsOn', 
        Pos     => [10, 15], 
        Title   => "Enable Shadows", 
        Active  => $enableShadows, 
        Tip     => "Enable client-side shadows on windows.\nNote:\nDesktop windows \
                    (with _NET_WM_WINDOW_TYPE_DESKTOP) never get shadow.", 
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('checkShadowsOn', 'clicked', sub {&check_shadows_on();});

sub check_shadows_on {
    $enableShadows = $win->is_active('checkShadowsOn');
    # deactivate/activate all shadow frame widgets
    $win->set_sensitive('checkDocksOn', $enableShadows);
    $win->set_sensitive('checkDragnDrop', $enableShadows);
    $win->set_sensitive('labelOpacity', $enableShadows);
    $win->set_sensitive('entryOpacity', $enableShadows);
    $win->set_sensitive('labelBlurRadius', $enableShadows);
    $win->set_sensitive('entryBlurRadius', $enableShadows);
    $win->set_sensitive('labelLeftOffset', $enableShadows);
    $win->set_sensitive('entryLeftOffset', $enableShadows);
    $win->set_sensitive('labelTopOffset', $enableShadows);
    $win->set_sensitive('entryTopOffset', $enableShadows);
    $win->set_sensitive('labelShadowColor', $enableShadows);
    $win->set_sensitive('entryShadowColor', $enableShadows);
    if ($win->is_active('radioXcompmgr')) {
        &set_xcompmgr_widgets();
    } else {
        &set_compton_widgets();
    }
    &config_changed();
}


# On Docks / Panels ----------------------------------------------------
$win->add_check_button( Name => 'checkDocksOn', 
        Pos     => [10, 35], 
        Title   => "On Docks / Panels", 
        Active  => $noDockPanels, 
        Sens    => $enableShadows, 
        Tip     => "Painting shadows on panels and docks.", 
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('checkDocksOn', 'clicked', sub{$noDockPanels = !($win->is_active('checkDocksOn')); &config_changed();});


# While drag'n'drop ----------------------------------------------------
$win->add_check_button( Name => 'checkDragnDrop', 
        Pos     => [10, 55], 
        Title   => "While drag'n'drop", 
        Active  => $whileDnD, 
        Sens    => $enableShadows, 
        Tip     => "Draw shadows on drag-and-drop windows.", 
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('checkDragnDrop', 'clicked', sub{$whileDnD = $win->is_active('checkDragnDrop'); &config_changed();});


# Opacity --------------------------------------------------------------
$win->add_label( Name => 'labelOpacity', 
        Pos     => [12, 90], 
        Title   => "Opacity:", 
        Sens    => $enableShadows, 
        Frame   => 'ShadowsFrame');

$win->add_entry( Name => 'entryOpacity', 
        Pos     => [145, 85], 
        Size    => [60, 25], 
        Title   => $ShadowOpacity, 
        Sens    => $enableShadows, 
        Tip     => "The opacity of shadows. (0.0 - 1.0, defaults to 0.75).",
        Align   => 'right',  
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('entryOpacity', 'changed', sub {$ShadowOpacity = $win->get_title('entryOpacity'); &config_changed(); return 0;});


# Blur Radius ----------------------------------------------------------
$win->add_label( Name => 'labelBlurRadius', 
        Pos     => [12, 120], 
        Title   => "Blur Radius:", 
        Sens    => $enableShadows, 
        Frame   => 'ShadowsFrame');

$win->add_entry( Name => 'entryBlurRadius', 
        Pos     => [145, 115], 
        Size    => [60, 25], 
        Title   => $BlurRadius, 
        Sens    => $enableShadows, 
        Tip     => "The blur radius for shadows, in pixels. (defaults to 12).",
        Align   => 'right',  
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('entryBlurRadius', 'changed', sub {$BlurRadius = $win->get_title('entryBlurRadius'); &config_changed(); return 0;});


# Left Offset ----------------------------------------------------------
$win->add_label( Name => 'labelLeftOffset', 
        Pos     => [12, 150], 
        Title   => "Left Offset:", 
        Sens    => $enableShadows, 
        Frame   => 'ShadowsFrame');

$win->add_entry( Name => 'entryLeftOffset', 
        Pos     => [145, 145], 
        Size    => [60, 25], 
        Title   => $LeftOffset, 
        Sens    => $enableShadows, 
        Tip     => "The left offset for shadows, in pixels. (defaults to -15).",
        Align   => 'right',  
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('entryLeftOffset', 'changed', sub {$LeftOffset = $win->get_title('entryLeftOffset'); &config_changed(); return 0;});


# Top Offset -----------------------------------------------------------
$win->add_label( Name => 'labelTopOffset', 
        Pos     => [12, 180], 
        Title   => "Top Offset:", 
        Sens    => $enableShadows, 
        Frame   => 'ShadowsFrame');

$win->add_entry( Name => 'entryTopOffset', 
        Pos     => [145, 175], 
        Size    => [60, 25], 
        Title   => $TopOffset, 
        Sens    => $enableShadows, 
        Tip     => "The top offset for shadows, in pixels. (defaults to -15).",
        Align   => 'right',  
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('entryTopOffset', 'changed', sub {$TopOffset = $win->get_title('entryTopOffset'); &config_changed(); return 0;});


# Shadow color ---------------------------------------------------------
$win->add_label( Name => 'labelShadowColor', 
        Pos     => [12, 210], 
        Title   => "Shadow color:", 
        Sens    => $enableShadows, 
        Frame   => 'ShadowsFrame');

$win->add_entry( Name => 'entryShadowColor', 
        Pos     => [145, 205], 
        Size    => [60, 25], 
        Title   => $ShadowColor, 
        Sens    => $enableShadows, 
        Tip     => "RGB colors of shadows. (defaults to 000000).",
        Align   => 'right',  
        Frame   => 'ShadowsFrame');
$win->add_signal_handler('entryShadowColor', 'changed', sub {$ShadowColor = $win->get_title('entryShadowColor'); &config_changed(); return 0;});


#-----------------------------------------------------------------------
# Fading
#-----------------------------------------------------------------------
$win->add_frame( Name => 'FadingFrame', 
        Pos     => [240, 70], 
        Size    => [220, 190], 
        Title   => " Fading ");


# Enable Fading --------------------------------------------------------
$win->add_check_button( Name => 'checkFadingOn', 
        Pos     => [10, 15], 
        Title   => "Enable Fading", 
        Active  => $enableFading,
        Tip     => "Enable in/out fading of windows.", 
        Frame   => 'FadingFrame');
$win->add_signal_handler('checkFadingOn', 'clicked', sub {&check_fading_on();});

sub check_fading_on {
    $enableFading = $win->is_active('checkFadingOn');;
    # deactivate/activate all shadow frame widgets
    $win->set_sensitive('checkOpacityChanged', $enableFading);
    $win->set_sensitive('checkOpenClose', $enableFading);
    $win->set_sensitive('labelFadeInSteps', $enableFading);
    $win->set_sensitive('entryFadeInSteps', $enableFading);
    $win->set_sensitive('labelFadeOutSteps', $enableFading);
    $win->set_sensitive('entryFadeOutSteps', $enableFading);
    $win->set_sensitive('labelFadeStepTime', $enableFading);
    $win->set_sensitive('entryFadeStepTime', $enableFading);
    &check_comp_on();
}


# On Opacity changed ---------------------------------------------------
$win->add_check_button( Name => 'checkOpacityChanged', 
        Pos     => [10, 35], 
        Title   => "On Opacity changed", 
        Active  => $onOpacityChanged,
        Sens    => $enableFading, 
        Tip     => "Enables fade effect when windows change their opacity.", 
        Frame   => 'FadingFrame');
$win->add_signal_handler('checkOpacityChanged', 'clicked', sub{$onOpacityChanged = $win->is_active('checkOpacityChanged'); &config_changed();});


# On Open / Close ------------------------------------------------------
$win->add_check_button( Name => 'checkOpenClose', 
        Pos     => [10, 55], 
        Title   => "On Open / Close", 
        Active  => $onOpenClose,
        Sens    => $enableFading, 
        Tip     => "Enables fade effect when windows open or close.", 
        Frame   => 'FadingFrame');
$win->add_signal_handler('checkOpenClose', 'clicked', sub{$onOpenClose = $win->is_active('checkOpenClose'); &config_changed();});


# Fade-in Steps --------------------------------------------------------
$win->add_label( Name => 'labelFadeInSteps', 
        Pos     => [12, 90], 
        Title   => "Fade-in Steps:", 
        Sens    => $enableFading, 
        Frame   => 'FadingFrame');

$win->add_entry( Name => 'entryFadeInSteps', 
        Pos     => [145, 85], 
        Size    => [60, 25], 
        Title   => $FadeInSteps, 
        Sens    => $enableFading, 
        Tip     => "Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028).",
        Align   => 'right',  
        Frame   => 'FadingFrame');
$win->add_signal_handler('entryFadeInSteps', 'changed', sub {$FadeInSteps = $win->get_title('entryFadeInSteps'); &config_changed(); return 0;});


# Fade-out Steps -------------------------------------------------------
$win->add_label( Name => 'labelFadeOutSteps', 
        Pos     => [12, 120], 
        Title   => "Fade-out Steps:", 
        Sens    => $enableFading, 
        Frame   => 'FadingFrame');

$win->add_entry( Name => 'entryFadeOutSteps', 
        Pos     => [145, 115], 
        Size    => [60, 25], 
        Title   => $FadeOutSteps, 
        Sens    => $enableFading, 
        Tip     => "Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03).",
        Align   => 'right',  
        Frame   => 'FadingFrame');
$win->add_signal_handler('entryFadeOutSteps', 'changed', sub {$FadeOutSteps = $win->get_title('entryFadeOutSteps'); &config_changed(); return 0;});


# Fade Step Time -------------------------------------------------------
$win->add_label( Name => 'labelFadeStepTime', 
        Pos     => [12, 150], 
        Title   => "Fade Step Time:", 
        Sens    => $enableFading, 
        Frame   => 'FadingFrame');

$win->add_entry( Name => 'entryFadeStepTime', 
        Pos     => [145, 145], 
        Size    => [60, 25], 
        Title   => $FadeStepTime, 
        Sens    => $enableFading, 
        Tip     => "The time between steps in fade step, in milliseconds. (> 0, defaults to 10).",
        Align   => 'right',  
        Frame   => 'FadingFrame');
$win->add_signal_handler('entryFadeStepTime', 'changed', sub {$FadeStepTime = $win->get_title('entryFadeStepTime'); &config_changed(); return 0;});


#-----------------------------------------------------------------------
# Opacity
#-----------------------------------------------------------------------
$win->add_frame( Name => 'OpacityFrame', 
        Pos     => [240, 270], 
        Size    => [220, 50], 
        Sens    => $xcompActive, 
        Title   => " Opacity ");

# Opacity on Menus -----------------------------------------------------
$win->add_label( Name => 'labelOpacityOnMenus', 
        Pos     => [12, 15], 
        Title   => "Opacity on Menus:", 
        Frame   => 'OpacityFrame');

$win->add_entry( Name => 'entryOpacityOnMenus', 
        Pos     => [145, 10], 
        Size    => [60, 25], 
        Title   => $OpacityOnMenus, 
        Tip     => "Default opacity for dropdown menus and popup menus. (0.0 - 1.0, defaults to 1.0).",
        Align   => 'right',  
        Frame   => 'OpacityFrame');
$win->add_signal_handler('entryOpacityOnMenus', 'changed', sub {$OpacityOnMenus = $win->get_title('entryOpacityOnMenus'); &config_changed(); return 0;});


#-----------------------------------------------------------------------
# Additional Parameters
#-----------------------------------------------------------------------
$win->add_frame( Name => 'AddParamFrame', 
        Pos     => [10, 330], 
        Size    => [450, 50], 
        Title   => " Additional Parameters ");

$win->add_entry( Name => 'entryAdditionalParams', 
        Pos     => [10, 10], 
        Size    => [425, 25], 
        Title   => $AdditionalParams, 
        Tip     => "Enter here paramters which are not accessible with the configurator.",
        Sens    => 1, 
        Frame   => 'AddParamFrame');
$win->add_signal_handler('entryAdditionalParams', 'changed', sub {$AdditionalParams = $win->get_title('entryAdditionalParams'); &config_changed(); return 0;});


#-----------------------------------------------------------------------
# Button bar
#-----------------------------------------------------------------------

# Save -----------------------------------------------------------------
$win->add_button( Name => 'saveButton', 
        Pos     => [15, 395], 
        Size    => [80, 25], 
        Title   => "Save", 
        Sens    => 0,
        Tip     => "Save settings.");
$win->add_signal_handler('saveButton', 'clicked', sub{&save();});

# save the configuration
sub save {
    &build_cmd();
    #print "comp_command \"$execString\" $config_path";
    $module->send("FuncWriteInfoStoreToFileAndSet comp_command \"$execString\" $config_path");
    $module->send("FuncWriteSetEnvToFileAndSet use_composite $useCompositor $config_path");
    $win->set_sensitive('saveButton', 0);
    $cfg_changed = 0;
}

# activate or deactivate the save button depending on a settings change
# Parameter is 1 (default) or 0
sub config_changed($) {
    my $value = shift;
    if (defined($value)) {
        $cfg_changed = $value;
    } else {
        $cfg_changed = 1;
    }
    $win->set_sensitive('saveButton', $cfg_changed);
}


# Help -----------------------------------------------------------------
$win->add_button( Name => 'helpButton', 
        Pos     => [135, 395], 
        Size    => [80, 25], 
        Title   => "Help", 
        Tip     => "Get help.");
$win->add_signal_handler('helpButton', 'clicked', \&open_help);

sub open_help {
    if ($win->is_active('radioXcompmgr')) {
        system("xterm -g 100x50 -n \"Help XcompMgr\" -T \"Help XcompMgr\" -e \"man xcompmgr\" &");
    } else {
        system("xterm -g 100x50 -n \"Help Compton\" -T \"Help Compton\" -e \"man compton\" &");
    }
}


# Run ------------------------------------------------------------------
$win->add_button( Name => 'runButton', 
        Pos     => [255, 395], 
        Size    => [90, 25], 
        Title   => $runButtonTitle, 
        Tip     => "Start or stop the choosen composite manager.");
$win->add_signal_handler('runButton', 'clicked', sub{&start_stop();});

# click-function to start or stop the composite manager
sub start_stop {
    if ($runButtonTitle eq 'Start') {
        &startComp();
    } else {
        &stopComp();
    }
}


# Cancel ---------------------------------------------------------------
$win->add_button( Name => 'cancelButton', 
        Pos     => [365, 395], 
        Size    => [90, 25], 
        Title   => "Cancel", 
        Tip     => "Cancel / Quit Composite Configurator.");
$win->add_signal_handler('cancelButton', 'clicked', \&check_before_quit);

# check before quit for unsaved changes
sub check_before_quit {
    if ($cfg_changed == 1) {
        my $response = $win->show_msg_dialog("warning", "yes-no", "You have unsaved changes! Continue anyway?");
        if ($response eq 'no') {
            return;
        }
    }
    Gtk2->main_quit;
}


# set widgets depending on the composite manager
if ($compmgr ne 'none') {
    if ($xcompActive == 1) {
        if ($compmgr eq 'compton') {
            $win->show_message("xcompmgr not installed. Switching to compton.");
            $win->set_sensitive('radioXcompmgr', 0);
            $win->set_sensitive('radioCompton', 1);
            $win->set_value('radioCompton', 'Active' => 1);
            &set_compton_widgets();
        } else {
            if($compmgr eq 'xcompmgr') {
                $win->set_sensitive('radioCompton', 0);
                $win->set_sensitive('radioXcompmgr', 1);
                $win->set_value('radioXcompmgr', 'Active' => 1);
                &set_xcompmgr_widgets();
            }
        }
    } else {
        if ($compmgr eq 'xcompmgr') {
            $win->show_message("compton not installed. Switching to xcompmgr.");
            $win->set_sensitive('radioCompton', 0);
            $win->set_sensitive('radioXcompmgr', 1);
            $win->set_value('radioXcompmgr', 'Active' => 1);
            $xcompActive = 1;
            &set_xcompmgr_widgets();
        } else {
            $win->set_sensitive('radioXcompmgr', 1);
            $win->set_sensitive('radioCompton', 1);
            $win->set_value('radioCompton', 'Active' => 1);
            &set_compton_widgets();
        }
    }
    # now we can set it :P
    config_changed(0);
} else {
    if ($useCompositor == 1) {
        $useCompositor = 0;
        $win->set_value('checkUse', $useCompositor);
        $module->send("FuncWriteSetEnvToFileAndSet use_composite $useCompositor $config_path");
    }
    
    # deactivate all frames
    $win->set_sensitive('CompFrame', 0);
    $win->set_sensitive('ShadowsFrame', 0);
    $win->set_sensitive('FadingFrame', 0);
    $win->set_sensitive('OpacityFrame', 0);
    $win->set_sensitive('AddParamFrame', 0);
    # deactivate all buttons except cancel
    $win->set_sensitive('saveButton', 0);
    $win->set_sensitive('helpButton', 0);
    $win->set_sensitive('runButton', 0);
    $win->show_msg_dialog("info", "ok", "No composite manager is installed.\nFor full functionality Xcompmgr or Compton must installed at least.");
}


########################################################################
# Common functions depending on the GUI
########################################################################

#-----------------------------------------------------------------------
# building the composite command for execution or saving
#-----------------------------------------------------------------------
sub build_cmd {
    $xcompActive == 1 ? $execString = $xcompmgr : $execString = $compton;
    
    if ($enableShadows != 0) {
        $execString = "$execString -c";
        if ($noDockPanels != 1) {$execString = "$execString -C";};
        if ($ShadowOpacity != 0.1) {$execString = "$execString -o $ShadowOpacity";};
        if ($BlurRadius != 12) {$execString = "$execString -r $BlurRadius";};
        if ($LeftOffset != -15) {$execString = "$execString -l $LeftOffset";};
        if ($TopOffset != -15) {$execString = "$execString -t $TopOffset";};
    }
    
    if ($enableFading != 0) {
        $execString = "$execString -f";
        if ($onOpacityChanged != 0) {
            if ($xcompActive == 1) {$execString = "$execString -F";}
        }
        if ($FadeInSteps != 0.028) {$execString = "$execString -I $FadeInSteps";};
        if ($FadeOutSteps != 0.03) {$execString = "$execString -O $FadeOutSteps";};
        if ($FadeStepTime != 10) {$execString = "$execString -D $FadeStepTime";};
    }
    
    if ($ShadowColor ne "000000") {
        my $dec_num = sprintf("%d", hex(substr($ShadowColor,0,2)));
        my $float_num = $dec_num/255;
        $ShadowColorR = sprintf("%.4f", $float_num);
        $execString = "$execString --shadow-red $ShadowColorR";

        $dec_num = sprintf("%d", hex(substr($ShadowColor,2,2)));
        $float_num = $dec_num/255;
        $ShadowColorG = sprintf("%.4f", $float_num);
        $execString = "$execString --shadow-green $ShadowColorG";

        $dec_num = sprintf("%d", hex(substr($ShadowColor,4,2)));
        $float_num = $dec_num/255;
        $ShadowColorB = sprintf("%.4f", $float_num);
        $execString = "$execString --shadow-blue $ShadowColorB";
    }
    
    if ($enableFading != 0) {
        if ($onOpenClose != 1) {$execString = "$execString --no-fading-openclose";}
    }

    if ($OpacityOnMenus != 0.0) {$execString = "$execString -m $OpacityOnMenus";}

    if ($AdditionalParams ne "") {$execString = "$execString $AdditionalParams";}
}


#-----------------------------------------------------------------------
# start the composite manager
#-----------------------------------------------------------------------
sub startComp {
    &build_cmd();
    my $pid = fork();
    if (defined $pid && $pid == 0) {
        system($execString);
        exit 0;
    }    
    $module->send("FuncStartFvwmTransSet");
    sleep 0.5;
    if (&CompOnTheRun()) {
        $win->set_title('runButton', $runButtonTitle);
    }
}


#-----------------------------------------------------------------------
# stop the composite manager
#-----------------------------------------------------------------------
sub stopComp {
    my $pid = fork();
    if (defined $pid && $pid == 0) {
        system("killall $stopCompmgr");
        exit 0;
    }    
    $module->send("FuncStopFvwmTransSet");
    sleep 0.5;
    unless (&CompOnTheRun()) {
        $win->set_title('runButton', $runButtonTitle);
    }
}


#-----------------------------------------------------------------------
# disable/enable widgets (not) supported by xcompmgr
#-----------------------------------------------------------------------
sub set_xcompmgr_widgets {
    $win->set_sensitive('checkDragnDrop', 0);
    $win->set_sensitive('labelShadowColor', 0);
    $win->set_sensitive('entryShadowColor', 0);
    
    if ($enableFading) {
        $win->set_sensitive('checkOpacityChanged', 1);
    }
    $win->set_sensitive('checkOpenClose', 0);
    $win->set_sensitive('OpacityFrame', 0);
}


#-----------------------------------------------------------------------
# disable/enable widgets (not) supported by compton
#-----------------------------------------------------------------------
sub set_compton_widgets {
    if ($enableShadows) {
        $win->set_sensitive('checkDragnDrop', 1);
        $win->set_sensitive('labelShadowColor', 1);
        $win->set_sensitive('entryShadowColor', 1);
    }
    
    $win->set_sensitive('checkOpacityChanged', 0);
    if ($enableFading) {
        $win->set_sensitive('checkOpenClose', 1);
        $win->set_sensitive('OpacityFrame', 1);
    }
}


#$win->show_and_run();
$win->show();

$module->eventLoop;

