Logo Search packages:      
Sourcecode: beryl-manager version File versions

main.c

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib.h>
#include <glib/gstdio.h>
#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 <signal.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)

//better error handling
#define manager_error(String) g_critical("%s: %s", String, g_strerror(errno))

/* enums for the Beryl options */
typedef enum
{
      AutoBinding,
      StrictBinding,
      XGLBinding
} BindingMode;

typedef enum
{
      AutoCOW,
      UseCOW,
      NoCOW
} COWMode;

typedef enum
{
      AutoRendering,
      IndirectRendering,
      XGLRendering
} RenderingMode;

typedef enum
{
      AutoPlatform,
      NvidiaPlatform,
      AIGLXPlatform,
      XGLPlatform
} PlatformMode;

typedef enum
{
      AutoRenderPath,
      TFPRenderPath,
      CopyRenderPath
} RenderPathMode;

Atom wmAtom;
Atom PopupRunning;
GMutex *mutx;
EggTrayIcon *mainIcon;
GtkWidget *menu;
GtkTooltips *tips;

/* options for Beryl command line */
RenderPathMode renderPath = AutoRenderPath;
PlatformMode platformMode = AutoPlatform;
RenderingMode renderingMode = AutoRendering;
COWMode cowMode = AutoCOW;
BindingMode bindingMode = AutoBinding;

gboolean noGLYield = 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;
gint WM = 0;
gint fallBackWM = 0;
gint DM = 0;
gint iconsize = 24;
gchar *displayname;
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_("Aquamarine (KDE Decorator)"), "aquamarine", 0},
      {N_("Heliodor (GNOME/Metacity Decorator)"), "heliodor", 0},
      {N_("Light Themable Decorator (yawd)"), "yawd", 0},
      {N_("GTK Window Decorator"), "gtk-window-decorator", 0},
      {N_("KDE Window Decorator"), "kde-window-decorator", 0},
};

#define numDM (gint)(sizeof(DMs)/sizeof(DMInfo))
WMInfo WMs[] = {
      {N_("Beryl"), 0, 0, 0, 0, 0, 0, 0},
      {N_("Compiz"), "compiz", "--replace gconf", "compiz", 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 (gint)(sizeof(WMs)/sizeof(WMInfo))
#define FALLBACKWM_OFFSET 2

GtkWidget *useFBItem;
GtkWidget *FBSubItem;
GtkWidget *DMSubItem;
GtkWidget *reloadDecoratorItem;

void launchWM();
void startWM();
void init_widgets();
void startBeryl();
void showMenu(guint, guint32);
static Window Window_With_Name(Display * dpy, Window top, char *name);


static void usage(const char *programName)
{
      printf(_("Usage: %s "
                   "[-d] [--no-force-window-manager] [--no-force-decorator] "
                   "[--help] [--version]" "\n"), programName);
}

void startApp(GtkWidget * w, gchar * command)
{
      g_spawn_command_line_async(command, NULL);
}

static void signalHandler(int sig)
{
      static int suspending = 0;

      switch (sig)
      {
      case SIGUSR1:
            //FIXME, here we should temporarily disable/hide the last "Quit" entry,
            //Could be missleading to the average user...
            showMenu(0, gtk_get_current_event_time());
            break;
      case SIGUSR2:
            if (!suspending)
            {
                  if (!WM)
                  {
                        WM = fallBackWM + FALLBACKWM_OFFSET;
                        startWM();
                        suspending = 1;
                  }
            }
            else
            {
                  WM = 0;
                  reloadingBeryl = TRUE;
                  startBeryl();
                  suspending = 0;
            }
            break;
      default:
            break;
      }
}

gchar *display_part(const gchar * p)
{
      gchar *name = g_strdup(p);
      gchar *tmp;

      if ((tmp = g_strrstr(name, ":")))
      {
            *tmp++ = 0;
            tmp = g_strdup(tmp);
            g_free(name);
            name = tmp;
      }

      if ((tmp = g_strrstr(name, ".")))
      {
            *tmp = 0;
      }

      return name;
}


void beryl_manager_log_handler(const gchar * log_domain,
                                             GLogLevelFlags log_level,
                                             const gchar * message, gpointer user_data)
{
      g_log_default_handler(log_domain, log_level, message, user_data);

      if (log_level <= G_LOG_LEVEL_WARNING)
            return;

      if (isatty(0))
            g_on_error_query(NULL);
      else
            abort();
}


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;
            i = g_key_file_get_integer(f, "wm-settings", "iconsize", &e);
            if (!e && (i >= 12 && i <= 128))
                  iconsize = i;
            e = NULL;

            i = g_key_file_get_integer(f, "beryl-settings", "render_path", &e);
            if (!e)
                  renderPath = (RenderPathMode) i;
            e = NULL;

            i = g_key_file_get_integer(f, "beryl-settings", "cow_mode", &e);
            if (!e)
                  cowMode = (COWMode) i;
            e = NULL;

            i = g_key_file_get_integer(f, "beryl-settings", "rendering_mode", &e);
            if (!e)
                  renderingMode = (RenderingMode) i;
            e = NULL;

            i = g_key_file_get_integer(f, "beryl-settings", "platform", &e);
            if (!e)
                  platformMode = (PlatformMode) i;
            e = NULL;

            i = g_key_file_get_integer(f, "beryl-settings", "binding", &e);
            if (!e)
                  bindingMode = (BindingMode) i;
            e = NULL;

            if (!XGL && NV9XXX)
            {
                  b = g_key_file_get_boolean(f, "beryl-settings",
                                                         "no_gl_yield", &e);
                  if (!e)
                        noGLYield = b;
                  e = NULL;
            }
            else
                  noGLYield = FALSE;
      }
      g_key_file_free(f);
      g_free(path);
}

void save_settings()
{
      gchar *path = g_strconcat(g_get_home_dir(), "/.beryl-managerrc", NULL);
      gchar *data;
      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_integer(f, "wm-settings", "iconsize", iconsize);
      g_key_file_set_boolean(f, "wm-settings", "use_fallback_wm", useFB);
      g_key_file_set_integer(f, "beryl-settings", "render_path", renderPath);
      g_key_file_set_integer(f, "beryl-settings", "cow_mode", cowMode);
      g_key_file_set_integer(f, "beryl-settings", "rendering_mode",
                                       renderingMode);
      g_key_file_set_integer(f, "beryl-settings", "platform", platformMode);
      g_key_file_set_integer(f, "beryl-settings", "binding", bindingMode);
      if (!XGL && NV9XXX)
            g_key_file_set_boolean(f, "beryl-settings", "no_gl_yield", noGLYield);
      data = g_key_file_to_data(f, NULL, NULL);
      g_file_set_contents(path, data, -1, NULL);
      g_key_file_free(f);
      g_free(path);
      g_free(data);
}
gboolean is_running(const gchar * command)
{
      gchar *cmd = g_strconcat("pidof ", command, NULL);
      gchar *pret;
      gint i;

      if (g_spawn_command_line_sync(cmd, &pret, NULL, NULL, NULL))
      {
            g_strchomp(pret);
            if (pret && *pret)
            {
                  gchar **pidlist = g_strsplit(pret, " ", 0);

                  i = 0;
                  while (pidlist[i])
                  {
                        if (atoi(pidlist[i]))
                        {
                              gchar *buffer;
                              gsize len;
                              gchar *file =
                                          g_strconcat("/proc/", pidlist[i], "/environ",
                                                            NULL);
                              if (g_file_get_contents(file, &buffer, &len, NULL))
                              {
                                    gchar *cp;

                                    for (cp = buffer; cp < (buffer + len);
                                           cp += strlen(cp) + 1)
                                    {
                                          if (strncmp(cp, "DISPLAY=", 8) == 0)
                                          {
                                                gchar *part = display_part(cp + 8);

                                                if (strcmp(part, displayname) == 0)
                                                {
                                                      g_strfreev(pidlist);
                                                      g_free(pret);
                                                      g_free(file);
                                                      g_free(buffer);
                                                      g_free(cmd);
                                                      g_free(part);
                                                      return TRUE;
                                                }
                                                g_free(part);
                                          }
                                    }
                              }
                              g_free(buffer);
                              g_free(file);
                        }
                        i++;
                  }
                  g_strfreev(pidlist);
            }
            g_free(pret);
      }
      g_free(cmd);
      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 popupClient(GtkWidget * w, GdkEventClient * e, gpointer d)
{
      static GdkAtom my_atom = GDK_NONE;

      if (my_atom == GDK_NONE)
            my_atom = gdk_atom_intern("beryl-manager-Popup", 1);
      if (e->message_type == my_atom)
      {
            showMenu(0, gtk_get_current_event_time());
            return TRUE;
      }
      return FALSE;
}

gboolean buttonUp(GtkWidget * w, GdkEventButton * e, gpointer d)
{
       if (hasMouse && e->button == 3)  
            showMenu(e->button, e->time);
      return TRUE;
}

gboolean buttonDown(GtkWidget * w, GdkEventButton * e, gpointer d) 
{ 
      if (hasMouse && e->button == 1 && e->type == 5) 
            startApp(w,"beryl-settings"); 
      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;
}

gboolean destroyNotify(GtkWidget * w, GdkEventClient * e, gpointer d)
{
      init_widgets();
      return TRUE;
}

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;
      gchar *s = NULL;

      if (decoratorLaunched && !reloadingDecorator)
            return NULL;

      decoratorLaunched = FALSE;
      s = g_strconcat(DMs[DM].Prog, " --replace", NULL);
      do
      {
            if (g_spawn_command_line_sync(s, NULL, NULL, &ex, NULL))
            {
                  decoratorLaunched = TRUE;
                  if (reloadingDecorator)
                        reloadingDecorator = FALSE;
            }
            else
            {
                  g_warning(_("Couldn't launch selected decorator:%s"),
                                DMs[DM].Name);
                  if (WIFEXITED(ex))      // returned something
                  {
                        g_warning(_("decorator %s returned unsuccessfully"),
                                      DMs[DM].Name);
                        if (WEXITSTATUS(ex))    // returned something other than 0
                        {
                              g_warning(_("decorator %s returned with non-zero status"),
                                            DMs[DM].Name);
                        }
                  }
                  else if (WIFSIGNALED(ex))
                  {
                        g_warning(_("decorator %s was killed by a signal"),
                                      DMs[DM].Name);
                        if (!decoratorSignalled(WTERMSIG(ex)))
                        {
                        }
                  }
            }
      }
      while (!decoratorLaunched);

      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()
{
      gint killed = 0;

      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 *pret;
                              gchar *cm = g_strconcat("pidof ", WMs[i].Grep, NULL);

                              if (!g_spawn_command_line_sync
                                    (cm, &pret, NULL, NULL, NULL))
                                    g_warning(_("No pidof, this may not work right."));
                              else
                              {
                                    g_strchomp(pret);
                                    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 =
                                                                                    display_part(cp + 8);
                                                                        if (strcmp(md, displayname) ==
                                                                              0)
                                                                        {
                                                                              //on same display, go ahead kill
                                                                              if (kill(pid, SIGTERM) !=
                                                                                    -1)
                                                                                    killed++;
                                                                        }
                                                                        g_free(md);
                                                                  }
                                                            }
                                                            g_free(e);
                                                      }
                                                      else
                                                      {
                                                            g_warning("Couldn't open %s", f);
                                                      }
                                                      g_free(f);
                                                }
                                          }
                                          g_free(pret);
                                    }
                              }
                              g_free(cm);
                        }
                  }
                  Window w = wmAtom ? XGetSelectionOwner(d, wmAtom) : None;

                  if (w != None)
                        XKillClient(d, w);
                  else if (killed)
                  {
                        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)
                                    manager_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;
      killWM();
      g_spawn_command_line_async(wm_command, NULL);
      g_free(wm_command);
}

#define BERYL_COMMAND_LINE_SIZE 150

gpointer berylThread(gpointer d)
{
      gint ex = 0;
      gchar beryl_command[BERYL_COMMAND_LINE_SIZE];

      if (XGL)
            g_strlcpy(beryl_command, "beryl-xgl", BERYL_COMMAND_LINE_SIZE);
      else
            g_strlcpy(beryl_command, "beryl", BERYL_COMMAND_LINE_SIZE);

      switch (renderPath)
      {
      case TFPRenderPath:
            g_strlcat(beryl_command, " --use-tfp", BERYL_COMMAND_LINE_SIZE);
            break;
      case CopyRenderPath:
            g_strlcat(beryl_command, " --use-copy", BERYL_COMMAND_LINE_SIZE);
            break;
      default:
            break;
      }

      switch (renderingMode)
      {
      case IndirectRendering:
            g_strlcat(beryl_command, " --indirect-rendering",
                          BERYL_COMMAND_LINE_SIZE);
            break;
      case XGLRendering:
            g_strlcat(beryl_command, " --xgl-rendering", BERYL_COMMAND_LINE_SIZE);
            break;
      default:
            break;
      }

      switch (cowMode)
      {
      case UseCOW:
            g_strlcat(beryl_command, " --use-cow", BERYL_COMMAND_LINE_SIZE);
            break;
      case NoCOW:
            g_strlcat(beryl_command, " --no-cow", BERYL_COMMAND_LINE_SIZE);
            break;
      default:
            break;
      }

      switch (platformMode)
      {
      case AIGLXPlatform:
            g_strlcat(beryl_command, " --force-aiglx", BERYL_COMMAND_LINE_SIZE);
            break;
      case NvidiaPlatform:
            g_strlcat(beryl_command, " --force-nvidia", BERYL_COMMAND_LINE_SIZE);
            break;
      case XGLPlatform:
            g_strlcat(beryl_command, " --force-xgl", BERYL_COMMAND_LINE_SIZE);
            break;
      default:
            break;
      }

      switch (bindingMode)
      {
      case StrictBinding:
            g_strlcat(beryl_command, " --strict-binding",
                          BERYL_COMMAND_LINE_SIZE);
            break;
      case XGLBinding:
            g_strlcat(beryl_command, " --xgl-binding", BERYL_COMMAND_LINE_SIZE);
            break;
      default:
            break;
      }

      if (noGLYield)
            g_strlcat(beryl_command, " --skip-gl-yield", BERYL_COMMAND_LINE_SIZE);

      berylLaunched = TRUE;
      while (berylLaunched)
      {
            killWM();
            if (!g_spawn_command_line_sync(beryl_command, NULL, NULL, &ex, NULL))
            {
                  if (XGL)
                        manager_error(_("can't execute beryl-xgl"));
                  else
                        manager_error(_("can't execute beryl"));
            }
            if (reloadingBeryl)
            {
                  reloadingBeryl = FALSE;
                  return NULL;
            }
            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 + FALLBACKWM_OFFSET;
            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()
{
      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
}

void startBeryl()
{
      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)
{
      if (WM == 0)
            reloadBeryl();
      else
            startWM();
}

void setWM(GtkWidget * w, gpointer p)
{
      gint i = GPOINTER_TO_INT(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 < 3);
            //gtk_widget_set_sensitive(FBSubItem,i==0 && useFB);
            gtk_widget_set_sensitive(DMSubItem, i < 3);
            for (j = 0; j < numDM; j++)
            {
                  gtk_widget_set_sensitive(DMs[j].Item, i < 3);
            }
            //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 = GPOINTER_TO_INT(p);

      if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
      {
            fallBackWM = i;
            save_settings();
      }
}

void toggleRenderingPath(GtkWidget * w, gpointer p)
{
      RenderPathMode rPath = GPOINTER_TO_INT(p);

      if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
      {
            renderPath = rPath;
            save_settings();
            reloadWM(w, p);
      }
}

void toggleCOW(GtkWidget * w, gpointer p)
{
      COWMode cow = GPOINTER_TO_INT(p);

      if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
      {
            cowMode = cow;
            save_settings();
            reloadWM(w, p);
      }
}

void togglePlatform(GtkWidget * w, gpointer p)
{
      PlatformMode platform = GPOINTER_TO_INT(p);

      if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
      {
            platformMode = platform;
            save_settings();
            reloadWM(w, p);
      }
}

void toggleBinding(GtkWidget * w, gpointer p)
{
      BindingMode binding = GPOINTER_TO_INT(p);

      if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
      {
            bindingMode = binding;
            save_settings();
            reloadWM(w, p);
      }
}

void toggleRendering(GtkWidget * w, gpointer p)
{
      RenderingMode rendering = GPOINTER_TO_INT(p);

      if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
      {
            renderingMode = rendering;
            save_settings();
            reloadWM(w, p);
      }
}

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 = GPOINTER_TO_INT(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") ||
                        is_running("compiz");
      }
}
gboolean detect_app(const gchar * app)
{
      gint ex;
      gchar *f = g_strdup_printf("sh -c 'which %s > /dev/null 2>&1'", app);

      if (!g_spawn_command_line_sync(f, NULL, NULL, &ex, NULL))
            manager_error(_("can't use this app, no which"));
      g_free(f);
      if (WIFEXITED(ex))
      {
            if (WEXITSTATUS(ex) == 0)
                  return TRUE;
      }
      else
            manager_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 + FALLBACKWM_OFFSET)
            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 setGLYield(GtkWidget * w, gpointer p)
{
      noGLYield = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
      save_settings();
      if (WM == 0)
            reloadBeryl();
}

GtkWidget *add_menu_group_item(GtkWidget * menu, GSList ** group,
                                             const gchar * name, gboolean show,
                                             gboolean check, GCallback callback,
                                             gpointer data)
{
      GtkWidget *mitem;

      mitem = gtk_radio_menu_item_new_with_label(*group, name);
      *group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);

      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), check);

      if (show)
            gtk_widget_show(mitem);
      else
            gtk_widget_hide(mitem);

      g_signal_connect(mitem, "toggled", callback, data);

      return mitem;
}

void init_menu()
{
      GtkWidget *submenu;
      GtkWidget *mitem;
      GtkWidget *smshell;
      GSList *renderPathGroup = NULL;
      GSList *cowGroup = NULL;
      GSList *platformGroup = NULL;
      GSList *bindingGroup = NULL;
      GSList *renderingGroup = NULL;
      GSList *wms = NULL;
      GSList *fbk = NULL;
      GSList *dms = NULL;
      gint i;

      menu = gtk_menu_new();
      g_object_ref(menu);

      if (detect_app("beryl-settings"))
      {
            mitem = gtk_image_menu_item_new_with_label(_("Beryl Settings Manager"));
            gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem),
                   make_image(DATADIR "/icons/hicolor/scalable/apps/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");
      }

      if (detect_app("emerald-theme-manager"))
      {
            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");
      }

      if (detect_app("emerald-theme-manager") || detect_app("beryl-settings"))
      {
            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(PIXMAPS_DIR "/wm-select.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 = add_menu_group_item(smshell, &wms, gettext(WMs[i].Name),
                                                      ((i == 0) ||
                                                       detect_wm(i)), (i == WM),
                                                      G_CALLBACK(setWM), GINT_TO_POINTER(i));
            WMs[i].Item = mitem;
      }

      mitem = gtk_image_menu_item_new_with_label(_("Advanced Beryl options"));
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem);
      gtk_widget_show(mitem);

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

      mitem = gtk_image_menu_item_new_with_label(_("Rendering path"));
      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
      gtk_widget_show(mitem);

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

      add_menu_group_item(smshell, &renderPathGroup, _("Automatic"), TRUE,
                                    (renderPath == AutoRenderPath),
                                    G_CALLBACK(toggleRenderingPath),
                                    GINT_TO_POINTER(AutoRenderPath));
      add_menu_group_item(smshell, &renderPathGroup, _("Texture From Pixmap"),
                                    TRUE, (renderPath == TFPRenderPath),
                                    G_CALLBACK(toggleRenderingPath),
                                    GINT_TO_POINTER(TFPRenderPath));
      add_menu_group_item(smshell, &renderPathGroup, _("Copy"), TRUE,
                                    (renderPath == CopyRenderPath),
                                    G_CALLBACK(toggleRenderingPath),
                                    GINT_TO_POINTER(CopyRenderPath));

      mitem = gtk_image_menu_item_new_with_label(_("Composite Overlay Window"));
      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
      gtk_widget_show(mitem);

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

      add_menu_group_item(smshell, &cowGroup, _("Automatic"), TRUE,
                                    (cowMode == AutoCOW), G_CALLBACK(toggleCOW),
                                    GINT_TO_POINTER(AutoCOW));
      add_menu_group_item(smshell, &cowGroup, _("Use COW"), TRUE,
                                    (cowMode == UseCOW), G_CALLBACK(toggleCOW),
                                    GINT_TO_POINTER(UseCOW));
      add_menu_group_item(smshell, &cowGroup, _("Don't use COW"), TRUE,
                                    (cowMode == NoCOW), G_CALLBACK(toggleCOW),
                                    GINT_TO_POINTER(NoCOW));

      mitem = gtk_image_menu_item_new_with_label(_("Rendering platform"));
      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
      gtk_widget_show(mitem);

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

      add_menu_group_item(smshell, &platformGroup, _("Automatic"), TRUE,
                                    (platformMode == AutoPlatform),
                                    G_CALLBACK(togglePlatform),
                                    GINT_TO_POINTER(AutoPlatform));
      add_menu_group_item(smshell, &platformGroup, _("Force Nvidia"), TRUE,
                                    (platformMode == NvidiaPlatform),
                                    G_CALLBACK(togglePlatform),
                                    GINT_TO_POINTER(NvidiaPlatform));
      add_menu_group_item(smshell, &platformGroup, _("Force AIGLX"), TRUE,
                                    (platformMode == AIGLXPlatform),
                                    G_CALLBACK(togglePlatform),
                                    GINT_TO_POINTER(AIGLXPlatform));
      add_menu_group_item(smshell, &platformGroup, _("Force XGL"), TRUE,
                                    (platformMode == XGLPlatform),
                                    G_CALLBACK(togglePlatform),
                                    GINT_TO_POINTER(XGLPlatform));

      mitem = gtk_image_menu_item_new_with_label(_("Binding"));
      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
      gtk_widget_show(mitem);

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

      add_menu_group_item(smshell, &bindingGroup, _("Automatic"), TRUE,
                                    (bindingMode == AutoBinding),
                                    G_CALLBACK(toggleBinding),
                                    GINT_TO_POINTER(AutoBinding));
      add_menu_group_item(smshell, &bindingGroup, _("Strict Binding"), TRUE,
                                    (bindingMode == StrictBinding),
                                    G_CALLBACK(toggleBinding),
                                    GINT_TO_POINTER(StrictBinding));
      add_menu_group_item(smshell, &bindingGroup, _("XGL Binding"), TRUE,
                                    (bindingMode == XGLBinding),
                                    G_CALLBACK(toggleBinding),
                                    GINT_TO_POINTER(XGLBinding));

      mitem = gtk_image_menu_item_new_with_label(_("Rendering"));
      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
      gtk_widget_show(mitem);

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

      add_menu_group_item(smshell, &renderingGroup, _("Automatic"), TRUE,
                                    (renderingMode == AutoRendering),
                                    G_CALLBACK(toggleRendering),
                                    GINT_TO_POINTER(AutoRendering));
      add_menu_group_item(smshell, &renderingGroup, _("Indirect Rendering"),
                                    TRUE, (renderingMode == IndirectRendering),
                                    G_CALLBACK(toggleRendering),
                                    GINT_TO_POINTER(IndirectRendering));
      add_menu_group_item(smshell, &renderingGroup, _("XGL Rendering"), TRUE,
                                    (renderingMode == XGLRendering),
                                    G_CALLBACK(toggleRendering),
                                    GINT_TO_POINTER(XGLRendering));

      if (!XGL && NV9XXX)
      {
            mitem = gtk_check_menu_item_new_with_label(_
                                                                           ("Disable GL Yield setting\n"
                                                                              "Use this to fix some redraw bugs"));
            gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mitem);
            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), noGLYield);
            gtk_widget_show(mitem);
            g_signal_connect(mitem, "toggled", G_CALLBACK(setGLYield), NULL);
      }

      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 < 3);
      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(PIXMAPS_DIR "/wd-select.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 < 3);

      for (i = 0; i < numDM; i++)
      {
            mitem = gtk_radio_menu_item_new_with_label(dms, gettext(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),
                                     GINT_TO_POINTER(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(PIXMAPS_DIR
                                                                   "/fall-back-wm-select.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 = FALLBACKWM_OFFSET; i < numWM; i++)
      {
            mitem = gtk_radio_menu_item_new_with_label(fbk, gettext(WMs[i].Name));
            fbk = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem));
            if ((i - FALLBACKWM_OFFSET) == 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),
                                     GINT_TO_POINTER(i - FALLBACKWM_OFFSET));
      }

      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_at_size(DATADIR
                                                                  "/icons/hicolor/scalable/apps/beryl-manager.svg",
                                                                  iconsize, iconsize, NULL);
      if (!pbuf)
            pbuf = gdk_pixbuf_new_from_file(DATADIR
                                                            "/icons/hicolor/24x24/apps/beryl-manager.png",
                                                            NULL);
      if (!pbuf)
            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
      {
            g_object_ref(G_OBJECT(pbuf));
            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-release-event", G_CALLBACK(buttonUp),
                              NULL);
      g_signal_connect(evbox, "button-press-event", G_CALLBACK(buttonDown), 
                              NULL); 
      g_signal_connect(evbox, "enter-notify-event", G_CALLBACK(enterNotify),
                               NULL);
      g_signal_connect(evbox, "leave-notify-event", G_CALLBACK(leaveNotify),
                               NULL);
      g_signal_connect(evbox, "destroy", G_CALLBACK(destroyNotify), NULL);
      g_signal_connect(mainIcon, "client-event", G_CALLBACK(popupClient), NULL);
      gtk_widget_show_all(GTK_WIDGET(mainIcon));
}

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))
            manager_error(_("can't use this app, no glxinfo or no grep"));
      if (WIFEXITED(ex))
      {
            if (WEXITSTATUS(ex) == 0)
                  NV9XXX = TRUE;
            else
                  NV9XXX = FALSE;
      }
      else
            manager_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))
            manager_error(_("can't use this app, no xvinfo or no grep"));
      if (WIFEXITED(ex))
      {
            if (WEXITSTATUS(ex) == 0)
                  XGL = TRUE;
            else
                  XGL = FALSE;
      }
      else
            manager_error(_("something went wrong with xvinfo or grep"));
}
int main(int argc, char **argv)
{
      gint i, found;
      gchar *buffer;
      gboolean daemon_mode = TRUE;
      Display *d;
      gboolean force_window_manager = TRUE;
      gboolean force_decorator = TRUE;
      Window running_window;

      //Intialise error handler
      g_log_set_handler(G_LOG_DOMAIN,
                                G_LOG_LEVEL_WARNING |
                                G_LOG_LEVEL_ERROR |
                                G_LOG_LEVEL_CRITICAL, beryl_manager_log_handler, NULL);

      //set the locale stuff 
      setlocale(LC_ALL, "");
      bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
      bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
      textdomain(GETTEXT_PACKAGE);

      //parse command line arguments
      for (i = 1; i < argc; i++)
      {
            if (strcmp(argv[i], "--help") == 0)
            {
                  usage(argv[0]);
                  return 0;
            }
            else if (strcmp(argv[i], "--version") == 0)
            {
                  printf(PACKAGE_STRING "\n");
                  return 0;
            }
            else if (strcmp(argv[i], "-d") == 0)
            {
                  daemon_mode = FALSE;
            }
            else if (strcmp(argv[i], "--no-force-window-manager") == 0)
            {
                  force_window_manager = FALSE;
            }
            else if (strcmp(argv[i], "--no-force-decorator") == 0)
            {
                  force_decorator = FALSE;
            }
            else
            {
                  usage(argv[0]);
                  return 1;
            }
      }

      //detach from console or not
      if (daemon_mode)
      {
            daemon(1, 1);
            close(0);
      }

      if (!XInitThreads())
      {
            g_warning(_("Can't init XLib thread support"));
            return 3;
      }

      d = XOpenDisplay(NULL);
      if ((running_window = Window_With_Name(d, DefaultRootWindow(d),
                                                               //                 GDK_WINDOW_XID(
                                                               // gdk_get_default_root_window()
                                                               // ),
                                                               "Beryl Manager")))
            // "Event Tester")))
      {
            XEvent clientEvent;
            gboolean missed = FALSE;

            PopupRunning = XInternAtom(d, "beryl-manager-Popup", 0);

            clientEvent.xclient.type = ClientMessage;
            clientEvent.xclient.window = running_window;
            clientEvent.xclient.message_type = PopupRunning;
            clientEvent.xclient.format = 32;
            clientEvent.xclient.display = d;
            clientEvent.xclient.data.l[0] = 0;
            clientEvent.xclient.data.l[1] = 0;
            clientEvent.xclient.data.l[2] = 0;
            clientEvent.xclient.data.l[3] = 0;
            clientEvent.xclient.data.l[4] = 0;
            //  gdk_error_trap_push ();
            missed = XSendEvent(d, running_window,
                                          False, NoEventMask, &clientEvent);
            XSync(d, False);
            // gdk_error_trap_pop ();
            return 0;
      }
      XCloseDisplay(d);

      // Some warning about changed behaviour for the unaware user
      /*
         if (!force_window_manager && !force_decorator) {
         if (!strcmp (PACKAGE_VERSION, "0.1.1")) {
         fprintf(stderr, "beryl-manager doesn't autostart window-manager/decorator\n"
         "any more. Please consult: man beryl-manager\n\n");
         }
         } 
       */
      //taken out because starting beryl is -the- reason for beryl-manager's existence.

      gtk_init(&argc, &argv);
      d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());

      buffer = g_strdup(DisplayString
                                (gdk_x11_display_get_xdisplay
                                 (gdk_display_get_default())));
      if (buffer)
      {
            displayname = display_part(buffer);
            g_free(buffer);
      }

      if (!g_thread_supported())
            g_thread_init(NULL);
      gdk_threads_init();
      gdk_threads_enter();
      mutx = g_mutex_new();


      // Check for the windows manager
      buffer = g_strconcat("WM_S", displayname, NULL);
      wmAtom = XInternAtom(d, buffer, 0);
      g_free(buffer);

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

      load_settings();
      init_widgets();
      init_menu();
      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 - FALLBACKWM_OFFSET;
                        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)
            manager_error("No Display Manager Found!");
      save_settings();

      found = False;
      for (i = 0; i < numDM && !found; i++)
      {
            if (is_running(DMs[i].Prog))
                  found = True;
      }
      if (!found || (force_decorator && !is_decor_running()))
      {
            g_thread_create(decorThread, NULL, FALSE, NULL);      // launch decorator
      }

      if (!force_window_manager)
      {
            found = False;
            for (i = 0; i < numWM && !found; i++)
                  if (is_wm_running(i))
                        found = True;
            if (!found)
                  launchWM();
      }
      else if (!is_wm_running(WM))
      {
            launchWM();
      }
      signal(SIGUSR1, signalHandler);
      signal(SIGUSR2, signalHandler);

      gtk_main();
      gdk_threads_leave();

      g_free(displayname);

      return 0;
}



/*      -       -       -       -       -       -       -       -       -

* [These functions are from the file "dsimple.c" used with xwininfo.]
*
* Written by Mark Lillibridge.   Last updated 7/1/87
*
*
* Window_With_Name: routine to locate a window with a given name on a display.
*                   If no window with the given name is found, 0 is returned.
*                   If more than one window has the given name, the first
*                   one found will be returned.  Only top and its subwindows
*                   are looked at.  Normally, top should be the Root Window.
*/
static Window Window_With_Name(Display * dpy, Window top, char *name)
{
      Window *children, dummy;
      unsigned int nchildren;
      unsigned i;
      Window w = 0;
      char *window_name;

      if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
      {
            XFree(window_name);
            return (top);
      }

      XFree(window_name);
      if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
            return (0);

      for (i = 0; i < nchildren; i++)
      {
            w = Window_With_Name(dpy, children[i], name);
            if (w)
                  break;
      }
      if (children)
            XFree((char *)children);
      return (w);
}

Generated by  Doxygen 1.6.0   Back to index