#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);
}
syntax highlighted by Code2HTML, v. 0.9.1