All pastes #186746 Raw Edit

Stuff

public text v1 · immutable
#186746 ·published 2006-09-30 12:30 UTC
rendered paste body
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gtk/gtk.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "eggtrayicon.h"
//intl stuff
#include<libintl.h>
#include<locale.h>
#define _(String) gettext (String)
#define gettext_noop(String) String
#define N_(String) gettext_noop (String)

Atom wmAtom;
GMutex * mutx;
EggTrayIcon * mainIcon;
GtkWidget * menu;
GtkTooltips * tips;
GtkWidget * useStrictBindingItem=NULL;
gboolean useStrictBind=FALSE;
gboolean hasMouse=FALSE;
gboolean berylLaunched=FALSE;
gboolean decoratorLaunched=FALSE;
gboolean reloadingBeryl=FALSE;
gboolean reloadingDecorator=FALSE;
gboolean XGL=FALSE;
gboolean NV9XXX=FALSE;
gboolean useFB=TRUE;
gboolean firstStart=TRUE;
gint WM=0;
gint fallBackWM=0;
gint DM=0;
typedef struct _DMInfo
{
    gchar * Name;
    gchar * Prog;
    GtkWidget * Item;
} DMInfo;
typedef struct _WMInfo
{
    gchar * Name;
    gchar * Prog;
    gchar * Opts;
    gchar * Grep;
    gint xXGL; // if nonzero, can't use on XGL
    gint Kill; // if nonzero, means has to be killall'd by its grep-name, and should NOT be xkill'd
    GtkWidget * Item;
    GtkWidget * FBItem;
} WMInfo;
typedef struct _XLSItem
{
    gchar * Command;
    Window w;
} XLSItem;
DMInfo DMs[] = {
    {N_("Standard Beryl Decorator (Emerald)"),       "emerald"                  ,0},
    {N_("Light Themable Decorator (yawd)"),          "yawd"                     ,0},
    {N_("GTK Window Decorator"),		     "gtk-window-decorator"	,0},
};
#define numDM (sizeof(DMs)/sizeof(DMInfo))
WMInfo WMs[]={
    {N_("Beryl"),                          0,                  0,              0               ,0,0,0,0},
    {N_("Compiz"),                         "compiz",            "--replace gconf"              ,0,0,0,0},
    {N_("Compiz with COW"),                "compiz",  "--use-cow --replace gconf"              ,0,0,0,0},
    {N_("Metacity (Gnome Window Manager)"), "metacity",         "--replace",    "metacity"      ,0,0,0,0},
    {N_("KWin (KDE Window Manager)"),       "kwin",             "--replace",    "kwin"          ,0,0,0,0},
    {N_("xfwm4 (XFCE Window Manager)"),     "xfwm4",            "",             "xfwm4"         ,0,1,0,0},
    {N_("WindowMaker"),                     "wmaker",           "",             "WindowMaker"   ,0,0,0,0},
    {N_("FluxBox"),                         "fluxbox",          "",             "fluxbox"       ,1,1,0,0},
    {N_("BlackBox"),                        "blackbox",         "",             "blackbox"      ,0,1,0,0},
    {N_("OpenBox"),                         "openbox",          "",             "openbox"       ,0,0,0,0},
    {N_("IceWM"),                           "icewm",            "",             "icewm"         ,0,0,0,0},
    {N_("Enlightenment"),                   "enlightenment",    "",             "enlightenment" ,0,1,0,0},
};
#define numWM (sizeof(WMs)/sizeof(WMInfo))
GtkWidget * useFBItem;
GtkWidget * FBSubItem;
GtkWidget * DMSubItem;
GtkWidget * reloadDecoratorItem;

void launchWM();

GSList * parse_xlsclients(gchar * output)
{
    GSList * ret = NULL;
    gchar * curpos;
    for(curpos=output;curpos && curpos[0];curpos=strstr(curpos,"\nWindow"))
    {
        XLSItem * i;
        gchar * p;
        gchar * q;
        curpos+=8;
        i=malloc(sizeof(XLSItem));
        i->w=strtol(curpos,NULL,16);
        p=strstr(curpos,"Command:  ");
        if (!p)
        {
            g_warning(_("Malformed xlsclients, no command?"));
            free(i);
            continue;
        }
        q=strchr(p,'\n');
        if (!q)
        {
            g_warning(_("Malformed xlsclients, no command?"));
            free(i);
            continue;
        }
        q[0]='\0';
        p=g_strdup(p+10);
        q[0]='\n';
        //trim p down to its basename
        q=strchr(p,' ');
        if (q)
            q[0]='\0';
        q=strrchr(p,'/');
        if (!q)
            q=p;
        else
            q++;
        i->Command=g_strdup(q);
        g_free(p);
        ret=g_slist_prepend(ret,i);
    }
    return ret;
}
void load_settings()
{
    gchar * path = g_strconcat(g_get_home_dir(),"/.beryl-managerrc",NULL);
    GKeyFile * f = g_key_file_new();
    if (g_key_file_load_from_file(f,path,0,NULL))
    {
        GError * e = NULL;
        gint i;
        gboolean b;
        i=g_key_file_get_integer(f,"wm-settings","active_wm",&e);
        if (!e)
            WM=i;
        e=NULL;
        i=g_key_file_get_integer(f,"wm-settings","fallback_wm",&e);
        if (!e)
            fallBackWM=i;
        e=NULL;
        i=g_key_file_get_integer(f,"wm-settings","active_dm",&e);
        if (!e)
            DM=i;
        e=NULL;
        b=g_key_file_get_boolean(f,"wm-settings","use_fallback_wm",&e);
        if (!e)
            useFB=b;
        e=NULL;
        if (!XGL && NV9XXX)
        {
            b=g_key_file_get_boolean(f,"beryl-settings",
                    "use_strict_binding",&e);
            if (!e)
                useStrictBind=b;
            e=NULL;
        }
        else
            useStrictBind=FALSE;
    }
    g_key_file_free(f);
    g_free(path);
}
void save_settings()
{
    gchar * path = g_strconcat(g_get_home_dir(),"/.beryl-managerrc",NULL);
    GKeyFile * f = g_key_file_new();
    g_key_file_set_integer(f,"wm-settings","active_wm",WM);
    g_key_file_set_integer(f,"wm-settings","fallback_wm",fallBackWM);
    g_key_file_set_integer(f,"wm-settings","active_dm",DM);
    g_key_file_set_boolean(f,"wm-settings","use_fallback_wm",useFB);
    if (!XGL && NV9XXX)
        g_key_file_set_boolean(f,"beryl-settings","use_strict_binding",
                useStrictBind);
    g_file_set_contents(path,g_key_file_to_data(f,NULL,NULL),-1,NULL);
    g_key_file_free(f);
    g_free(path);
}
gboolean is_running(const gchar * command)
{
    gint ex;
    if (!g_spawn_command_line_sync(
                g_strdup_printf("sh -c 'pidof %s > /dev/null'",command),
                NULL,NULL,&ex,NULL))
        g_error(_("can't use this app, no ps or grep"));
    if (WIFEXITED(ex))
    {
        if (WEXITSTATUS(ex)==0)
            return TRUE;
    }
    else
        g_error(_("something went wrong with ps or grep"));
    return FALSE;
}
gboolean is_decor_running()
{
    if (DM>numDM || DM<0)
        DM=0;
    return (is_running(DMs[DM].Prog));
}

void showMenu(guint button,guint32 time)
{
    gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,time);
}
gboolean buttonUp(GtkWidget * w, GdkEventButton * e, gpointer d)
{
    if (hasMouse)
        showMenu(e->button,e->time);
    return TRUE;
}
gboolean enterNotify(GtkWidget * w, GdkEventCrossing * e, gpointer d)
{
    hasMouse=TRUE;
    return TRUE;
}
gboolean leaveNotify(GtkWidget * w, GdkEventCrossing * e, gpointer d)
{
    hasMouse=FALSE;
    return TRUE;
}
void startApp(GtkWidget * w, gchar * command)
{
    g_spawn_command_line_async(command,NULL);
}
gboolean decoratorSignalled(gint signal)
{
    g_warning(_("Decorator caught deadly signal %d"),signal);
    return FALSE; // terminate for now
}
gboolean berylSignalled(gint signal)
{
    g_warning(_("Beryl caught deadly signal %d"),signal);
    return FALSE; // terminate for now
}
gpointer decorThread(gpointer d)
{
    gint ex=0;
    decoratorLaunched=TRUE;
    while(decoratorLaunched)
    {
        gchar * s = g_strconcat(DMs[DM].Prog," --replace",NULL);
        if (!g_spawn_command_line_sync(s,NULL,NULL,&ex,NULL))
        {
            g_warning(_("Couldn't launch selected decorator:%s"),DMs[DM].Name);
            decoratorLaunched=FALSE;
        }
        else if (reloadingDecorator)
        {
            g_free(s);
            reloadingDecorator=FALSE;
            return NULL;
        }
        else if (WIFEXITED(ex)) // returned something
        {
            if (WEXITSTATUS(ex)) // returned something other than 0
            {
                decoratorLaunched=FALSE;
            }
        }
        else if (WIFSIGNALED(ex)) // killed by a signal
        {
            if (!decoratorSignalled(WTERMSIG(ex)))
            {
                decoratorLaunched=FALSE;
            }
        }
        g_free(s);
    }
    return NULL;
}
void killIfWM(XLSItem * i, Display * d)
{
    gint j;
    for (j=1;j<numWM;j++)
    {
        if (!WMs[j].Kill)
        {
            if (strcmp(i->Command,WMs[j].Grep)==0)
            {
                g_message(_("Killing window %x for client %s."),(unsigned int)i->w,WMs[j].Name);
                XKillClient(d,i->w);
            }
        }
    }
}
void freeXLS(XLSItem * i, gpointer p)
{
    g_free(i->Command);
    free(i);
}
void killWM()
{
    if (!g_mutex_trylock(mutx))
        return;
    {
        Display * d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
        XLockDisplay(d);
        {
            gint i;
            for (i=1;i<numWM;i++)
            {
                if (WMs[i].Kill)
                {
                    gchar * cm = g_strconcat("pidof ",WMs[i].Grep,NULL);
                    gchar * pret;
                    if (!g_spawn_command_line_sync(cm,&pret,NULL,NULL,NULL))
                        g_warning(_("No pidof, this may not work right."));
                    else
                    {
                        if (pret)
                        {
                            gchar * cret;
                            if (strlen(pret))
                            {
                                if (pret[strlen(pret)-1]=='\n')
                                    pret[strlen(pret)-1]='\0';
                                for (cret=pret-1;cret;cret=strchr(cret,' '))
                                {
                                    gchar * p;
                                    gchar * e;
                                    gchar * f;
                                    pid_t pid;
                                    gsize l;
                                    cret++;
                                    p=strchr(cret,' ');
                                    if (p)
                                        p[0]='\0';
                                    f=g_strdup_printf("/proc/%s/environ",cret);
                                    pid=strtol(cret,NULL,10);
                                    if (p)
                                        p[0]=' ';
                                    if (g_file_get_contents(f,&e,&l,NULL))
                                    {
                                        gchar * cp;
                                        for(cp=e;(cp-e)<l;cp+=strlen(cp)+1)
                                        {
                                            if (strncmp(cp,"DISPLAY=",8)==0)
                                            {
                                                //might be killable
                                                gchar * md = getenv("DISPLAY");
                                                if (strcmp(cp+8,md)==0)
                                                {
                                                    //on same display, go ahead kill
                                                    kill(pid,SIGTERM);
                                                }
                                            }
                                        }
                                        g_free(e);
                                    }
                                    else
                                    {
                                        g_warning("Couldn't open %s",f);
                                    }
                                    g_free(f);
                                }
                            }
                            g_free(pret);
                        }
                    }
                    g_free(cm);
                }
            }
            Window w=XGetSelectionOwner(d,wmAtom);
            if (w!=None)
                XKillClient(d,w);
            else
            {
                gchar * cli;
                GSList * xls;
                g_warning(_("Couldn't find a Selection Owner, perhaps no WM running?\nOtherwise, manually kill your wm, and report the bug to the developers, it doesn't follow the standards.\nFalling back to looking for a defined WM in xlsclients."));
                if (!g_spawn_command_line_sync("xlsclients -l",&cli,NULL,NULL,NULL))
                {
                    g_warning(_("No xlsclients, this may not work right."));
                }
                else
                {
                    if (!cli)
                        g_error(_("No output from xlsclients, bailing."));
                    xls=parse_xlsclients(cli);
                    g_free(cli);
                    g_slist_foreach(xls,(GFunc)killIfWM,d);
                    g_slist_foreach(xls,(GFunc)freeXLS,NULL);
                    g_slist_free(xls);
                }
            }
            XSync(d,FALSE);
        }
        XUnlockDisplay(d);
    }
    g_mutex_unlock(mutx);
}
void startWM()
{
    gchar * wm_command=g_strjoin(" ",WMs[WM].Prog,WMs[WM].Opts,NULL);
    berylLaunched=FALSE;
    firstStart=FALSE;
    killWM();
    g_spawn_command_line_async(wm_command,NULL);
    g_free(wm_command);
}
gpointer berylThread(gpointer d)
{
    gint ex=0;
    gchar * beryl_command;
    if (XGL)
        beryl_command = "beryl-xgl";
    else
    {
        if (useStrictBind)
            beryl_command = "beryl --strict-binding";
        else
            beryl_command = "beryl";
    }
    berylLaunched=TRUE;
    while(berylLaunched)
    {
        killWM();
        g_spawn_command_line_sync(beryl_command,NULL,NULL,&ex,NULL);
        if (reloadingBeryl)
        {
            reloadingBeryl=FALSE;
            return NULL;
        }
        else if (firstStart)
        {
            firstStart=FALSE;
        }
        else if (WIFEXITED(ex)) // returned something
        {
            if (WEXITSTATUS(ex)) // returned something other than 0
            {
                berylLaunched=FALSE;
            }
        }
        else if (WIFSIGNALED(ex)) // killed by a signal
        {
            if (!berylSignalled(WTERMSIG(ex)))
            {
                berylLaunched=FALSE;
            }
        }
    }
    //if this thread exits, and WM is still beryl, fall back into the fall back WM
    if (WM==0 && useFB)
    {
        WM=fallBackWM+1;
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(WMs[WM].Item),TRUE);
        //gtk_widget_set_sensitive(useFBItem,FALSE);
        gtk_widget_set_sensitive(DMSubItem,FALSE);
        gtk_widget_set_sensitive(reloadDecoratorItem,FALSE);
        //gtk_widget_set_sensitive(FBSubItem,FALSE);
        //for(ex=1;ex<numWM;ex++)
        //{
        //    gtk_widget_set_sensitive(WMs[ex].FBItem,FALSE);
        //}
        for(ex=0;ex<numDM;ex++)
        {
            gtk_widget_set_sensitive(DMs[ex].Item,FALSE);
        }
        launchWM();
    }
    return NULL;
}
void reloadBeryl()
{
    firstStart=FALSE;
    if (berylLaunched)
        reloadingBeryl=TRUE;
    g_thread_create(berylThread,NULL,FALSE,NULL); // launch beryl
    if (!decoratorLaunched && !is_decor_running())
        g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator
}
gboolean killB(gpointer p)
{
    if (firstStart && WM==0)
    {
        reloadBeryl();
    }
    return FALSE;
}
void startBeryl()
{
    if (firstStart)
    {
        g_timeout_add(4000,(GSourceFunc) killB,NULL);
    }
    if (!berylLaunched)
        g_thread_create(berylThread,NULL,FALSE,NULL); // launch beryl
    if (!decoratorLaunched && !is_decor_running())
        g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator
}
void reloadDecorator(GtkWidget * w, gpointer p)
{
    if (decoratorLaunched)
        reloadingDecorator=TRUE;
    g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator
}
void launchWM()
{
    save_settings();
    if (WM==0)
        startBeryl();
    else
        startWM();
}
void reloadWM(GtkWidget * w, gpointer p)
{
    firstStart=FALSE;
    if (WM==0)
        reloadBeryl();
    else
        startWM();
}
void setWM(GtkWidget * w, gpointer p)
{
    gint i = (gint)p;
    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
    {
        gint j;
        if (i!=WM)
        {
            WM=i;
            launchWM();
        }
        //gtk_widget_set_sensitive(useFBItem,i==0);
        gtk_widget_set_sensitive(reloadDecoratorItem,i==0);
        //gtk_widget_set_sensitive(FBSubItem,i==0 && useFB);
        gtk_widget_set_sensitive(DMSubItem,i==0);
        for(j=0;j<numDM;j++)
        {
            gtk_widget_set_sensitive(DMs[j].Item,i==0);
        }
        //for (j=1;j<numWM;j++)
        //{
        //    gtk_widget_set_sensitive(WMs[j].FBItem,i==0 && useFB);
        //}
        save_settings();
    }
}
void setFallbackWM(GtkWidget * w, gpointer p)
{
    gint i = (gint)p;
    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
    {
        fallBackWM=i;
        save_settings();
    }
}
void toggleFB(GtkWidget * w, gpointer p)
{
    gint i;
    useFB=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
    gtk_widget_set_sensitive(FBSubItem,useFB);
    for (i=1;i<numWM;i++)
        gtk_widget_set_sensitive(WMs[i].FBItem,useFB);
    save_settings();
}
void setDM(GtkWidget * w, gpointer p)
{
    gint i = (gint)p;
    if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
    {
        DM=i;
        save_settings();
        reloadDecorator(w,p);
    }
}
GtkWidget * make_image(gchar * path)
{
    GdkPixbuf * p;
    gint w,h;
    gtk_icon_size_lookup(GTK_ICON_SIZE_MENU,&w,&h);
    p = gdk_pixbuf_new_from_file_at_size(path,w,h,NULL);
    if (!p)
        return gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE,
                    GTK_ICON_SIZE_MENU);
    else
        return gtk_image_new_from_pixbuf(p);
}
void quitMe(GtkWidget * w, gpointer p)
{
    gtk_main_quit();
}
gboolean is_wm_running(gint wm)
{
    const gchar * nam;
    if (wm>0)
    {
        nam=WMs[wm].Grep;
        return is_running(nam);
    }
    else
    {
        return is_running("beryl") || is_running("beryl-xgl");
    }
}
gboolean detect_app(const gchar * app)
{
    gint ex;
    if (!g_spawn_command_line_sync(
                g_strdup_printf("sh -c 'which %s > /dev/null'",app),
                NULL,NULL,&ex,NULL))
        g_error(_("can't use this app, no which"));
    if (WIFEXITED(ex))
    {
        if (WEXITSTATUS(ex)==0)
            return TRUE;
    }
    else
        g_error(_("something went wrong with which"));
    return FALSE;
}
gboolean detect_wm(gint wm)
{
    if (!XGL || !WMs[wm].xXGL)
    {
        if (detect_app(WMs[wm].Prog))
           return TRUE; 
    }
    if (wm == WM)
        WM=-1;
    if (wm == fallBackWM+1)
       fallBackWM=-1; 
    return FALSE;
}
gboolean detect_dm(gint dm)
{
    if (detect_app(DMs[dm].Prog))
        return TRUE;
    if (dm == DM)
        DM=-1;
    return FALSE;
}
void setUseStrict(GtkWidget * w, gpointer p)
{
    useStrictBind=gtk_check_menu_item_get_active(
            GTK_CHECK_MENU_ITEM(w));
    save_settings();
    if (WM==0) reloadBeryl();
}
void init_menu()
{
    GtkWidget * mitem;
    GtkWidget * smshell;
    GSList * wms = NULL;
    GSList * fbk = NULL;
    GSList * dms = NULL;
    gint i;
    
    menu = gtk_menu_new();
    g_object_ref(menu);

    mitem = gtk_image_menu_item_new_with_label(_("Beryl Settings Manager"));
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            make_image(PIXMAPS_DIR "/beryl-settings.svg"));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);
    g_signal_connect(mitem,"activate",G_CALLBACK(startApp),"beryl-settings");
    
    mitem = gtk_image_menu_item_new_with_label(_("Emerald Theme Manager"));
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            make_image(PIXMAPS_DIR "/emerald-theme-manager-icon.png"));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);
    g_signal_connect(mitem,"activate",G_CALLBACK(startApp),"emerald-theme-manager");
    
    mitem = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);
    
    mitem = gtk_image_menu_item_new_with_label(_("Reload Window Manager"));
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU));
    g_signal_connect(mitem,"activate",G_CALLBACK(reloadWM),NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);
    
    mitem = gtk_image_menu_item_new_with_label(_("Select Window Manager"));
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            make_image(DATADIR "/beryl/icon.png"));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);
    
    smshell=gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell);
    
    for (i=0;i<numWM;i++)
    {
        mitem = gtk_radio_menu_item_new_with_label(wms,WMs[i].Name);
        wms=gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
        if (i==WM)
            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),TRUE);
        gtk_menu_shell_append(GTK_MENU_SHELL(smshell),mitem);
        if (i==0 || detect_wm(i))
            gtk_widget_show(mitem);
        else
            gtk_widget_hide(mitem);
        g_signal_connect(mitem,"toggled",G_CALLBACK(setWM),(gpointer)i);
        WMs[i].Item=mitem;
    }

    if (!XGL && NV9XXX)
    {
        mitem = gtk_check_menu_item_new_with_label(_(
                    "Enable Strict Binding\n"
                    "Use this to avoid blank windows bug"));
        gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
        gtk_check_menu_item_set_active(
                GTK_CHECK_MENU_ITEM(mitem),useStrictBind);
        gtk_widget_show(mitem);
        g_signal_connect(mitem,"toggled",G_CALLBACK(setUseStrict),NULL);
        useStrictBindingItem=mitem;
    }
    mitem = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    mitem = gtk_image_menu_item_new_with_label(_("Reload Window Decorator"));
    reloadDecoratorItem = mitem;
    gtk_widget_set_sensitive(reloadDecoratorItem,WM==0);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU));
    g_signal_connect(mitem,"activate",G_CALLBACK(reloadDecorator),NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    mitem = gtk_image_menu_item_new_with_label(_("Select Window Decorator"));
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            make_image(DATADIR "/beryl/icon.png"));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    smshell=gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell);
    DMSubItem=mitem;
    gtk_widget_set_sensitive(GTK_WIDGET(DMSubItem),WM==0);

    for (i=0;i<numDM;i++)
    {
        mitem = gtk_radio_menu_item_new_with_label(dms,DMs[i].Name);
        dms=gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
        if (i==DM)
            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),TRUE);
        gtk_menu_shell_append(GTK_MENU_SHELL(smshell),mitem);
        if (detect_dm(i))
            gtk_widget_show(mitem);
        else
            gtk_widget_hide(mitem);
        g_signal_connect(mitem,"toggled",G_CALLBACK(setDM),(gpointer)i);
        DMs[i].Item=mitem;
    }

    mitem = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    mitem = gtk_check_menu_item_new_with_label(_("Launch Fall-back Window\nManager if beryl crashes"));
    useFBItem = mitem;
    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),useFB);
    g_signal_connect(mitem,"toggled",G_CALLBACK(toggleFB),NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    mitem = gtk_image_menu_item_new_with_label(_("Select Fall-back Window Manager"));
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
            make_image(DATADIR "/beryl/icon.png"));
    FBSubItem=mitem;
    gtk_widget_set_sensitive(FBSubItem,useFB);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    smshell=gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell);

    for (i=1;i<numWM;i++)
    {
        mitem = gtk_radio_menu_item_new_with_label(fbk,WMs[i].Name);
        fbk=gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
        if ((i-1)==fallBackWM)
            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),TRUE);
        gtk_widget_set_sensitive(mitem,useFB);
        gtk_menu_shell_append(GTK_MENU_SHELL(smshell),mitem);
        if (detect_wm(i))
            gtk_widget_show(mitem);
        else
            gtk_widget_hide(mitem);
        WMs[i].FBItem=mitem;
        g_signal_connect(mitem,"toggled",G_CALLBACK(setFallbackWM),(gpointer)(i-1));
    }

    mitem = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);

    mitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL);
    g_signal_connect(mitem,"activate",G_CALLBACK(quitMe),NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem);
    gtk_widget_show(mitem);
}
void init_widgets()
{
    GtkWidget * icon;
    GtkWidget * evbox;
    GdkPixbuf * pbuf;
    tips = gtk_tooltips_new();
    mainIcon = egg_tray_icon_new(_("Beryl Manager"));
    evbox = gtk_event_box_new();
    gtk_event_box_set_visible_window(GTK_EVENT_BOX(evbox),FALSE);
    gtk_tooltips_set_tip(tips,evbox,_("Beryl Manager"),_("Manage various things related to Beryl"));
    pbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR "/beryl-manager.png",NULL);
    if (!pbuf)
        icon = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE,GTK_ICON_SIZE_SMALL_TOOLBAR);
    else
        icon = gtk_image_new_from_pixbuf(pbuf);
    gtk_container_add(GTK_CONTAINER(mainIcon),evbox);
    gtk_container_add(GTK_CONTAINER(evbox),icon);
    //g_signal_connect(evbox,"button-press-event",G_CALLBACK(buttonDown),NULL);
    g_signal_connect(evbox,"button-release-event",G_CALLBACK(buttonUp),NULL);
    g_signal_connect(evbox,"enter-notify-event",G_CALLBACK(enterNotify),NULL);
    g_signal_connect(evbox,"leave-notify-event",G_CALLBACK(leaveNotify),NULL);
    gtk_widget_show_all(GTK_WIDGET(mainIcon));
    init_menu();
}
void detect_nvidia()
{
    //find out if we have XGL
    gint ex=0;
    if (!g_spawn_command_line_sync("sh -c 'glxinfo | grep -i NVIDIA > /dev/null'",
                NULL,NULL,&ex,NULL))
        g_error(_("can't use this app, no glxinfo or no grep"));
    if (WIFEXITED(ex))
    {
        if (WEXITSTATUS(ex)==0)
            NV9XXX=TRUE;
        else
            NV9XXX=FALSE;
    }
    else
        g_error(_("something went wrong with glxinfo or grep"));

}
void detect_xgl()
{
    //find out if we have XGL
    gint ex=0;
    if (!g_spawn_command_line_sync("sh -c 'xvinfo | grep -i Xgl > /dev/null'",
                NULL,NULL,&ex,NULL))
        g_error(_("can't use this app, no xvinfo or no grep"));
    if (WIFEXITED(ex))
    {
        if (WEXITSTATUS(ex)==0)
            XGL=TRUE;
        else
            XGL=FALSE;
    }
    else
        g_error(_("something went wrong with xvinfo or grep"));
}
int main(int argc, char ** argv)
{
    gint fd;
    gint e;
    Display * d;

    //set the locale stuff 
    setlocale(LC_ALL,"");
    bindtextdomain("beryl-manager","/usr/share/locale");
    textdomain("beryl-manager");

    for (fd=0;fd<argc;fd++)
        if (strcmp(argv[fd],"-d")==0)
            break;
    if (fd==argc)
        daemon(0,1);
    
    fd = creat(g_strconcat(g_get_home_dir(),"/.beryl-manager.lock",NULL)
            ,00755);
    e=errno;
    if (fd==-1)
    {

        g_warning(_("Couldn't open lockfile.\nError:%s"),strerror(e));
	//example to get localization 
	//g_warning(gettext("Couldn't open lockfile.\nError:%s"),strerror(e));

        return 1;
    }
    if (flock(fd,LOCK_EX | LOCK_NB)!=0)
    {  
        e=errno;      
        g_warning(_("Can't run more than one beryl-manager.\n(couldn't obtain lock) Error:%s"),strerror(e));
        return 2;
    }
    dprintf(fd,"%d\n",getpid()); 
    if (!XInitThreads())
    {
        g_warning(_("Can't init XLib thread support"));
        return 3;
    }
    gtk_init(&argc,&argv);

    d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    wmAtom = XInternAtom(d,"WM_S0",0);
    if (!g_thread_supported()) g_thread_init(NULL);
    mutx=g_mutex_new();

    detect_xgl();
    if (!XGL) detect_nvidia();

    load_settings();
    init_widgets();
    if (WM<0 || WM>(numWM))
        WM=-1;
    if (WM==-1)
    {
        //set WM to beryl for now
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(WMs[0].Item),TRUE);
    }
    if (fallBackWM<0 || fallBackWM > (numWM-1))
        fallBackWM=-1;
    if (fallBackWM==-1)
    {
        //we have to find a fall back WM that exists
        gint i;
        for (i=1;i<numWM;i++)
        {
            if (detect_wm(i))
            {
                gtk_check_menu_item_set_active(
                        GTK_CHECK_MENU_ITEM(WMs[i].FBItem),TRUE);
                fallBackWM=i-1;
                break;
            }
        }
    }
    if (fallBackWM==-1)
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(useFBItem),FALSE);
    if (DM<0 || DM > numDM)
        DM=-1;
    if (DM==-1)
    {
        //we have to find a DM that exists
        gint i;
        for (i=0;i<numDM;i++)
        {
            if (detect_dm(i))
            {
                gtk_check_menu_item_set_active(
                        GTK_CHECK_MENU_ITEM(DMs[i].Item),TRUE);
                DM=i;
                break;
            }
        }
    }
    if (DM==-1)
        g_error("No Display Manager Found!");
    save_settings();

    if (!is_wm_running(WM))
        launchWM();
    gtk_main();
    return 0;
}