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;
}